home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / language / harvest.cpt / Harvest C / Tcl 6.2 / tclMac.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-28  |  90.9 KB  |  3,543 lines

  1.  
  2. /* 
  3.  * Copyright 1992 Tim Endres
  4.  *
  5.  * Permission to use, copy, modify, and distribute this
  6.  * software and its documentation for any purpose and without
  7.  * fee is hereby granted, provided that the above copyright
  8.  * notice appear in all copies. Tim Endres makes no representations
  9.  * about the suitability of this software for any purpose.
  10.  * It is provided "as is" without express or implied warranty.
  11.  */
  12.  
  13. /* The following comments by Eric Sink
  14.  
  15.     What I have done is attempt to isolate the tcl port, and document
  16.     what needs to be done in order to integrate tcl into an app.  The way
  17.     I actually did this was to take the tcl code from Tim Endres' tickle,
  18.     and integrate it into Harvest C.  Along the way, I've filled in the
  19.     missing pieces, made the necessary modifications for THINK C, and
  20.     tried to find the places where app specific customizations are
  21.     required.  I have attempted to document these in the code.
  22.     
  23.     Rather than completely remove all application-specific code, I have
  24.     left it all in, and attempted to document it.  In this way, what
  25.     remains will serve as an example.  Generally, application specific
  26.     code is accompanied by a comment explaining its purpose, and what you
  27.     must do to replace it.  The comment will include the word CUSTOM, for
  28.     easy searching.
  29.     
  30.     This version of tcl 6.2 contains many extensions specifically for the
  31.     Macintosh.  Some of these extension bring up dialog boxes, and those
  32.     dialog boxes are stored in resources.  You must integrate the macTcl 
  33.     resource file into your application as well.
  34.     
  35.     To support Tcl in your application means that your app may be controlled
  36.     through tcl scripts.  You will install the tcl interpreter into your app,
  37.     including this file.  You will probably want to provide a number of extensions
  38.     to the Tcl language which are specific to your application.  Don't put them
  39.     in this file.
  40.     
  41.     When you create a Tcl interpreter, you must initialize it to include all
  42.     the Mac extensions contained here, as well as your own extensions.  My code,
  43.     which appears elsewhere, looks like this :
  44.     
  45.     myInterp = Tcl_CreateInterp();     base Tcl routine 
  46.     Tcl_InitMacintosh(myInterp);     defined herein - install Mac extensions 
  47.     InitHarvestTcl(myInterp);         CUSTOM replace with your own app's inittcl 
  48.     init_environment();                 defined herein - initialize env variables 
  49.  
  50.     Then you must provide an interface to Tcl, actually more than one.
  51.     You must provide support for the 'misc' 'dosc' AppleEvent.  Code to handle
  52.     this appears below.  This will allow your app to communicate with others
  53.     applications which support tcl.
  54.  
  55.     You will also want to provide some form of user interface, to allow the user
  56.     to enter tcl commands and run scripts.  In Harvest C, I provide a shell window,
  57.     much like MPW (and like tickle for that matter).  The source code to this
  58.     interface is included in this distribution (you must use the THINK Class
  59.     Library with THINK C in order to use it).
  60.     
  61.     You must provide a place to put Feedback, stdout/stderr, and user input.
  62.     Each application may wish to handle these in its own way.
  63.     
  64. */
  65.  
  66. #pragma segment TCL
  67.  
  68. #include <stdlib.h>
  69. #include <AppleEvents.h>
  70. #include <Aliases.h>
  71. #include "tcl.h"
  72. #include <time.h>
  73. #include "XTCL.h"
  74.  
  75. /* The following include files are application specific for Harvest C.
  76.     You will need to delete these, and you will probably need to somehow
  77.     declare the interfaces to your application. CUSTOM
  78. */
  79. #include "CHarvestApp.h"
  80. #include "CTclShell.h"
  81.  
  82. extern int errno;
  83. extern int macintoshErr;
  84. extern Str255 MyVersion;
  85.  
  86. int WDDirID(short);
  87. int WDVolRef(short);
  88.  
  89. extern CHarvestApp *gApplication;    /* Harvest C specific declaration CUSTOM */
  90.  
  91. char *custom_name        = "tcl";
  92. char *custom_longname    = "Harvest C";    /* change to your own app CUSTOM */
  93. int   patchlevel        = 0;
  94. char *tcl_defaultfile    = "tcl_default";
  95. char *tcl_version        = "6.2";
  96.  
  97.  
  98. #define SFSaveDisk        (* (short *) 0x0214)
  99. #define CurDirStore        (* (long *)  0x0398)
  100.  
  101. #ifdef THINK_C
  102. char *pathname();
  103. char *fullname();
  104. char *dirpathname();
  105. typedef int (*PFI)();
  106. #include <stdio.h>
  107. #include <string.h>
  108. #include <Packages.h>
  109.  
  110. /* CUSTOM You should define a function called UniversalFilter which is the
  111. standard filter proc for your app.  NULL works fine for me, but you might
  112. not think so. */
  113.  
  114. #define UniversalFilter NULL
  115.  
  116. /* CUSTOM Your application must provide some way for Tcl to send feedback
  117.     messages to the user.  Harvest C provides a Tcl shell window where all
  118.     user input is entered.  Feedback messages are sent to this window as well.
  119.     At various places in the code below, Tcl may call Feedback().  The
  120.     arguments to Feedback() are of the printf genre.  You must provide
  121.     a substitute routine.  Since I use the THINK Class Library,
  122.     my solution is to implement a method called Hprintf
  123.     in my CTclShell object, defining this to be FeedBack.
  124. */
  125.  
  126. extern CTclShell *gShell;
  127. #define Feedback gShell->Hprintf
  128.  
  129. /* CUSTOM These two variables must be initialized when your program
  130.         starts up.  The idea is to set app_ref num equal to the
  131.         reference number of the application resource file.  xtcl_refnum
  132.         is the reference number of a file of XTCL resources which
  133.         are available to the application.  I insert the following line
  134.         in my program startup code :
  135.         
  136.             app_refnum = xtcl_refnum = CurResFile();
  137. */
  138.  
  139. short app_refnum;    
  140. short xtcl_refnum;
  141.  
  142. OSType def_text_file_creator = 'ALFA';    /* CUSTOM change this to whatever you want */
  143.  
  144. /* The following two variables appear to be necessary but I do not fully understand
  145.     their function or use.  Tim ? */
  146.  
  147. unsigned long g_cron_interval;
  148. unsigned long g_next_cron_time;
  149.  
  150. /* CUSTOM Change the following two lines if you want to customize the cursors
  151.     management. */
  152. #define UInitCursor InitCursor
  153. #define WatchCursorOn() SetCursor(*GetCursor(watchCursor))
  154.  
  155. #define    MFOSEvent                    app4Evt    /* event used by MultiFinder */
  156. #define    MFSuspendResumeMessage        1        /* high byte of suspend/resume event message */
  157. #define    MFResumeMask                1        /* bit of message field for resume vs. suspend */
  158. #define    MFMouseMovedMessage            0xFA    /* high byte of mouse-moved event message */
  159.  
  160. #define keyStdOutObject                'StdO'
  161.  
  162. #endif
  163.  
  164. extern int            tcl_handle_output();
  165.  
  166. Handle                tcl_Houtput_sethdl();
  167. extern PFI            Tcl_SetPrintProcedure();
  168. extern PFI            Tcl_GetPrintProcedure();
  169.  
  170. FrameButton(mydialog, button)
  171. DialogPtr       mydialog;
  172. short                   button;
  173. {
  174. short   myoval, mytype;
  175. Handle  myhandle;
  176. Rect    myrect;
  177. char    mypat[8];
  178.  
  179.         PenNormal();
  180.         PenSize(3, 3);
  181.         *((long *)&mypat[0]) = (long)'\245\132\245\132';
  182.         *((long *)&mypat[4]) = (long)'\245\132\245\132';
  183.         GetDItem(mydialog, button, &mytype, &myhandle, &myrect);
  184.         if (myhandle != NULL) {
  185.                 if ((**((ControlHandle)myhandle)).contrlHilite == 255)
  186.                         PenPat(qd.gray);
  187.                 myoval = (myrect.bottom - myrect.top) * 4 / 5;
  188.                 InsetRect(&myrect, -4, -4);
  189.                 FrameRoundRect(&myrect, myoval, myoval);
  190.                 }
  191.         PenNormal();
  192.         }
  193.  
  194. MySetText(DialogPtr mydialog,int myItem,char            * myText)
  195. {
  196. short   item;
  197. Rect    myrect;
  198. Handle  myhandle;
  199.  
  200.         c2pstr(myText);
  201.         GetDItem(mydialog, myItem, &item, &myhandle, &myrect);
  202.         SetIText(myhandle, myText);
  203.         p2cstr(myText);
  204.         }
  205.  
  206. MyGetText(mydialog, myItem, myText)
  207. DialogPtr       mydialog;
  208. short           myItem;
  209. char            *myText;
  210. {
  211. short   item;
  212. Rect    myrect;
  213. Handle  myhandle;
  214.  
  215.         GetDItem(mydialog, myItem, &item, &myhandle, &myrect);
  216.         GetIText(myhandle, myText);
  217.         p2cstr(myText);
  218.         }
  219.  
  220. MyHiliteControl(mydialog, myItem, state)
  221. DialogPtr       mydialog;
  222. int                     myItem;
  223. int                     state;
  224. {
  225. short           item;
  226. Rect            myrect;
  227. Handle          myhandle;
  228.  
  229.         GetDItem(mydialog, myItem, &item, &myhandle, &myrect);
  230.         HiliteControl((ControlHandle)myhandle, state);
  231.         }
  232.  
  233. MySetControl(mydialog, myItem, myValue)
  234. DialogPtr       mydialog;
  235. int                     myItem;
  236. int                     myValue;
  237. {
  238. short           item;
  239. Rect            myrect;
  240. Handle          myhandle;
  241.  
  242.         GetDItem(mydialog, myItem, &item, &myhandle, &myrect);
  243.         SetCtlValue((ControlHandle)myhandle, myValue);
  244.         }
  245.  
  246. int MyGetControl(mydialog, myItem)
  247. DialogPtr       mydialog;
  248. int                     myItem;
  249. {
  250. short           item;
  251. Rect            myrect;
  252. Handle          myhandle;
  253.  
  254.         GetDItem(mydialog, myItem, &item, &myhandle, &myrect);
  255.         return GetCtlValue((ControlHandle)myhandle);
  256.         }
  257.  
  258. MySetTitle(mydialog, myItem, myTitle)
  259. DialogPtr       mydialog;
  260. int                     myItem;
  261. char            *myTitle;
  262. {
  263. short           item;
  264. Rect            myrect;
  265. Handle  myhandle;
  266.         GetDItem(mydialog, myItem, &item, &myhandle, &myrect);
  267.         c2pstr(myTitle);
  268.         SetCTitle((ControlHandle)myhandle, myTitle);
  269.         p2cstr(myTitle);
  270.         }
  271.  
  272. MyGetTitle(mydialog, myItem, myTitle)
  273. DialogPtr       mydialog;
  274. int                     myItem;
  275. char            *myTitle;
  276. {
  277. short           item;
  278. Rect            myrect;
  279. Handle          myhandle;
  280.  
  281.         GetDItem(mydialog, myItem, &item, &myhandle, &myrect);
  282.         GetCTitle((ControlHandle)myhandle, myTitle);
  283.         p2cstr(myTitle);
  284.         }
  285.  
  286.  
  287. tcl_feedback_output(str)
  288. char    *str;
  289. {
  290.     Feedback("%.240s", str);
  291.     }
  292.  
  293. tcl_dev_null_output(str)
  294. char    *str;
  295. {
  296. #pragma unused (str)
  297.  
  298.     }
  299.  
  300. /* CUSTOM Your application must support the notion of stdout for use with the
  301.     puts command.  You must define the following routine to accept a string
  302.     argument, and print it to your application's notion of stdout.  I handle
  303.     this the same way I do Feedback, by dumping it to the shell window.
  304. */
  305.     
  306. tcl_print_tclshell(str)
  307. char *str;
  308. {
  309.     gShell->Hprintf("%s",str);
  310. }
  311.  
  312. run_DoScript(script_handle, result_handle, stdout_handle)
  313. Handle        script_handle;
  314. Handle        result_handle;
  315. Handle        stdout_handle;
  316. {
  317. int            result;
  318. int            delete_interp = 0;
  319. PFI            saveproc;
  320. Handle        myhandle = NULL;
  321. char        command[128];
  322. Tcl_Interp    *interp;
  323.  
  324.     WatchCursorOn();
  325.     
  326.     /* create a Tcl interpreter for the session */
  327.     interp = (gShell->myInterp);
  328.     
  329.     saveproc = Tcl_SetPrintProcedure(tcl_dev_null_output);
  330.     sprintf(command, "set AEVENT 1\n");
  331.     result = Tcl_Eval(interp, command, 0, (char **)0);
  332.     if (result != TCL_OK)
  333.         Feedback("ERROR %d on <%s>", result, command);
  334.     Tcl_SetPrintProcedure(saveproc);
  335.  
  336.     result = Tcl_Interp_Handle(interp, script_handle, result_handle, stdout_handle);
  337.     if (result == TCL_OK)
  338.         {
  339.         result = noErr;
  340.         }
  341.     
  342.     saveproc = Tcl_SetPrintProcedure(tcl_dev_null_output);
  343.     sprintf(command, "set AEVENT 0\n");
  344.     result = Tcl_Eval(interp, command, 0, (char **)0);
  345.     Tcl_SetPrintProcedure(saveproc);
  346.  
  347.     UInitCursor();
  348.     
  349.     return result;
  350.     }
  351.  
  352. run_AE_tcl_script(theFSS, result_handle, stdout_handle)
  353. FSSpec        *theFSS;
  354. Handle        result_handle;
  355. Handle        stdout_handle;
  356. {
  357. int            result = noErr, wderr;
  358. short        wdrefnum;
  359. Handle        saveH, myhandle = NULL;
  360. PFI            saveproc;
  361. Tcl_Interp    *interp;
  362. char        command[128];
  363.  
  364.     WatchCursorOn();
  365.     
  366.     /* create a Tcl interpreter for the session */
  367.     interp = (gShell->myInterp);
  368.     
  369.     saveproc = Tcl_SetPrintProcedure(tcl_dev_null_output);
  370.     sprintf(command, "set AEVENT 1\n");
  371.     result = Tcl_Eval(interp, command, 0, (char **)0);
  372.     if (result != TCL_OK)
  373.         Feedback("ERROR %d on <%s>", result, command);
  374.         
  375.     wderr = OpenWD(theFSS->vRefNum, theFSS->parID, 'ERIK', &wdrefnum);
  376.     if (wderr == noErr)
  377.         SetVol(NULL, wdrefnum);
  378.     else
  379.         Feedback("Error %d OpenWD().", wderr);
  380.     
  381.     if (stdout_handle == NULL)
  382.         {
  383.         myhandle = NewHandle(0);
  384.         if (myhandle == NULL)
  385.             {
  386.             Feedback("Error #%d allocating a stdout handle.", MemError());
  387.             return -1770;
  388.             }
  389.         else
  390.             saveH = tcl_Houtput_sethdl(myhandle);
  391.         }
  392.     else
  393.         saveH = tcl_Houtput_sethdl(stdout_handle);
  394.     
  395.     Tcl_SetPrintProcedure(tcl_handle_output);
  396.  
  397.     sprintf(command, "source \"%.*s\"\n", theFSS->name[0], &theFSS->name[1]);
  398.     result = Tcl_Eval(interp, command, 0, (char **)0);
  399.  
  400.     if (wderr == noErr)
  401.         wderr = CloseWD(wdrefnum);
  402.     
  403.     if (result == TCL_OK)
  404.         {
  405.         result = noErr;
  406.         if (result_handle != NULL)
  407.             {
  408.             tcl_Houtput_sethdl(result_handle);
  409.             if (interp->result != NULL && *(interp->result) != '\0')
  410.                 (* Tcl_GetPrintProcedure()) (interp->result);
  411.             }
  412.         }
  413.      else
  414.         {
  415.         result = -1771;
  416.         (* Tcl_GetPrintProcedure()) ( (result == TCL_ERROR) ? "\015Error: " : "\015Bad Result: " );
  417.         (* Tcl_GetPrintProcedure()) ( (interp->result == NULL) ? "<NULL>" : interp->result );
  418.         }
  419.     
  420.     Tcl_SetPrintProcedure(tcl_dev_null_output);
  421.     sprintf(command, "set AEVENT 0\n");
  422.     Tcl_Eval(interp, command, 0, (char **)0);
  423.  
  424.     Tcl_SetPrintProcedure(saveproc);
  425.     tcl_Houtput_sethdl(saveH);
  426.     
  427.     if (myhandle != NULL)
  428.         DisposHandle(myhandle);
  429.  
  430.     UInitCursor();
  431.  
  432.     return result;
  433.     }
  434.  
  435. run_named_tcl_script(filename, interp, print_proc)
  436. char        *filename;    /* Pascal */
  437. Tcl_Interp    *interp;
  438. PFI            print_proc;
  439. {
  440. int            result = noErr;
  441. int            delete_interp = 0;
  442. PFI            saveproc;
  443. char        command[128];
  444.  
  445.     WatchCursorOn();
  446.     
  447.     if (interp == (Tcl_Interp *)0) {
  448.         interp = (gShell->myInterp);
  449.         }
  450.     
  451.     if (print_proc != (PFI)0)
  452.         saveproc = Tcl_SetPrintProcedure(print_proc);
  453.  
  454.     sprintf(command, "source \"%.*s\"\n", filename[0], &filename[1]);
  455.     result = Tcl_Eval(interp, command, 0, (char **)0);
  456.  
  457.     if (result == TCL_OK)
  458.         {
  459.         result = noErr;
  460.         if (interp->result != NULL && *(interp->result) != '\0')
  461.             (* Tcl_GetPrintProcedure()) (interp->result);
  462.         }
  463.      else
  464.         {
  465.         (* Tcl_GetPrintProcedure()) ( (result == TCL_ERROR) ? "Error: " : "Bad Result: " );
  466.         (* Tcl_GetPrintProcedure()) ( (interp->result == NULL) ? "<NULL>" : interp->result );
  467.         }
  468.     
  469.     if (print_proc != (PFI)0)
  470.         Tcl_SetPrintProcedure(saveproc);
  471.         
  472.     UInitCursor();
  473.  
  474.     return result;
  475.     }
  476.  
  477.  
  478. run_tcl_script(interp, print_proc)
  479. Tcl_Interp    *interp;
  480. PFI            print_proc;
  481. {
  482. int            result;
  483. int            delete_interp = 0;
  484. PFI            saveproc;
  485. char        command[128];
  486. Point        mypoint;
  487. SFReply        myreply;
  488. SFTypeList    mytypes;
  489.  
  490.     mypoint.h = mypoint.v = 75;
  491.     mytypes[0] = 'TEXT';
  492.     MyGetFile(mypoint, "\pScript:", NULL, (CheckOption()?-1:1), mytypes, NULL, &myreply);
  493.     if (myreply.good) {
  494.  
  495.         WatchCursorOn();
  496.         
  497.         if (interp == (Tcl_Interp *)0) {
  498.             interp = (gShell->myInterp);
  499.             }
  500.         
  501.         if (print_proc != (PFI)0)
  502.             saveproc = Tcl_SetPrintProcedure(print_proc);
  503.  
  504.         SetVol(NULL, myreply.vRefNum);
  505.         sprintf(command, "source \"%.*s\"\n", myreply.fName[0], &myreply.fName[1]);
  506.         
  507.         result = Tcl_Eval(interp, command, 0, (char **)0);
  508.  
  509.         if (result == TCL_OK)
  510.             {
  511.             if (interp->result != NULL && *(interp->result) != '\0')
  512.                 (* Tcl_GetPrintProcedure()) (interp->result);
  513.             }
  514.          else
  515.             {
  516.             (* Tcl_GetPrintProcedure()) ( (result == TCL_ERROR) ? "Error: " : "Bad Result: " );
  517.             (* Tcl_GetPrintProcedure()) ( (interp->result == NULL) ? "<NULL>" : interp->result );
  518.             }
  519.         
  520.         if (print_proc != (PFI)0)
  521.             Tcl_SetPrintProcedure(saveproc);
  522.         
  523.         UInitCursor();
  524.         }
  525.     
  526.     }
  527.  
  528.  
  529. int
  530. Cmd_DoAlertNote(clientData, interp, argc, argv)
  531. char        *clientData;
  532. Tcl_Interp    *interp;
  533. int            argc;
  534. char        **argv;
  535. {
  536. int        i;
  537. char    format_str[32];
  538. #pragma unused (clientData)
  539.  
  540.     if (argc > 6)
  541.         {
  542.         Tcl_AppendResult(interp, "too many arguments, limit 5", (char *) NULL);
  543.         return TCL_ERROR;
  544.         }
  545.         
  546.     format_str[0] = '\0';
  547.     for (i=1; i<6 && i<argc; i++)
  548.         strcat(format_str, "%s ");
  549.     
  550.     message_note(format_str, argv[1], argv[2], argv[3], argv[4], argv[5]);
  551.     
  552.     return TCL_OK;
  553.     }
  554.  
  555. int
  556. Cmd_Feedback(clientData, interp, argc, argv)
  557. char        *clientData;
  558. Tcl_Interp    *interp;
  559. int            argc;
  560. char        **argv;
  561. {
  562. int        i;
  563. char    output[256];
  564. #pragma unused (interp, clientData, argc)
  565.  
  566.     output[0] = '\0';
  567.     for (i = 1 ; i < argc && (strlen(output) + strlen(argv[i]) + 2) < 240 ; ++i) {
  568.         strcat(output, argv[i]);
  569.         strcat(output, " ");
  570.         }
  571.  
  572.     Feedback("%.240s", output);
  573.     
  574.     return TCL_OK;
  575.     }
  576.  
  577. static short        _current_working_directory = 0;
  578. static short        _current_working_vrefnum = 0;
  579. static long            _current_working_dirid = 2;
  580.  
  581. /* Note that two versions of the cd command are presented here.  I am using
  582. the latter one, since I could not get Tim Endres' version working under THINK C.
  583. The latter code was written by Pete Keleher.
  584. */
  585.  
  586. int
  587. Cmd_DoCD(clientData, interp, argc, argv)
  588. char        *clientData;
  589. Tcl_Interp    *interp;
  590. int            argc;
  591. char        **argv;
  592. {
  593. #ifdef ENDRES
  594. int            myerr;
  595. char        path[256], *ptr;
  596. HParamBlockRec    pb;
  597. WDPBRec        wpb;
  598. CInfoPBRec    cpb;
  599. #pragma unused (clientData)
  600.  
  601.     if (argc != 2)
  602.         {
  603.         Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  604.             " dirName\"", (char *) NULL);
  605.         return TCL_ERROR;
  606.         }
  607.  
  608.     strcpy(path, argv[1]);
  609.     ptr = strchr(path, ':');
  610.     if (path[0] != ':' && ptr != NULL)
  611.         {
  612.         *(ptr + 1) = '\0';
  613.         c2pstr(path);
  614.         pb.volumeParam.ioCompletion = 0;
  615.         pb.volumeParam.ioVRefNum = 0;
  616.         pb.volumeParam.ioNamePtr = (unsigned char *) path;
  617.         pb.volumeParam.ioVolIndex = -1;
  618.         myerr = PBHGetVInfo(&pb, FALSE);
  619.         if (myerr != noErr) {
  620.             macintoshErr = myerr;
  621.             Tcl_AppendResult(interp, "\"", argv[0], "\" PBHGetVInfo(", argv[1], ") ",
  622.                                     Tcl_MacError(interp), (char *) NULL);
  623.             return TCL_ERROR;
  624.             }
  625.         wpb.ioWDVRefNum = pb.volumeParam.ioVRefNum;
  626.         wpb.ioWDDirID = 2;
  627.         }
  628.     else
  629.         {
  630.         path[0] = '\0';
  631.         wpb.ioCompletion = 0;
  632.         myerr = PBHGetVol(&wpb, FALSE);
  633.         if (myerr != noErr) {
  634.             macintoshErr = myerr;
  635.             Tcl_AppendResult(interp, "\"", argv[0], "\" PBHGetVolInfo(", argv[1], ") ",
  636.                                     Tcl_MacError(interp), (char *) NULL);
  637.             return TCL_ERROR;
  638.             }
  639.         }
  640.  
  641.     strcpy(path, argv[1]);
  642.     c2pstr(path);
  643.     cpb.hFileInfo.ioCompletion = 0;                /* Synchronous */
  644.     cpb.hFileInfo.ioNamePtr = (unsigned char *) path;
  645.     cpb.hFileInfo.ioVRefNum = wpb.ioWDVRefNum;    /* Returned here */
  646.     cpb.hFileInfo.ioFDirIndex = 0;                /* Use ioDirID and ioNamePtr */
  647.     cpb.hFileInfo.ioDirID = wpb.ioWDDirID;        /* same offset as ioFlNum */
  648.     myerr = PBGetCatInfo(&cpb, (Boolean)0);        /* Synchronous */
  649.     if (myerr != noErr) {
  650.         macintoshErr = myerr;
  651.         Tcl_AppendResult(interp, "\"", argv[0], "\" PBGetCatInfo(", argv[1], ") ",
  652.                                 Tcl_MacError(interp), (char *) NULL);
  653.         return TCL_ERROR;
  654.         }
  655.     else if ((cpb.hFileInfo.ioFlAttrib & ioDirMask) == 0) {
  656.         Tcl_AppendResult(interp, "\"", argv[1], "\" not a directory", (char *) NULL);
  657.         return TCL_ERROR;
  658.         }
  659.     else {
  660.         wpb.ioCompletion = 0;
  661.         wpb.ioVRefNum = wpb.ioWDVRefNum;
  662.         wpb.ioNamePtr = (unsigned char *) NULL;
  663.         wpb.ioWDDirID = cpb.hFileInfo.ioDirID;
  664.         myerr = PBHSetVol(&wpb, FALSE);
  665.         if (myerr != noErr) {
  666.             macintoshErr = myerr;
  667.             Tcl_AppendResult(interp, "\"", argv[0], "\" PBHSetVol() ",
  668.                                     Tcl_MacError(interp), (char *) NULL);
  669.             return TCL_ERROR;
  670.             }
  671.         else {
  672.             wpb.ioWDProcID = 'ERIK';
  673.             myerr = PBOpenWD(&wpb, FALSE);
  674.             if (myerr == noErr) {
  675.                 _current_working_directory = wpb.ioVRefNum;
  676.                 _current_working_vrefnum = wpb.ioWDVRefNum;
  677.                 _current_working_dirid = cpb.hFileInfo.ioDirID;
  678.                 }
  679.             else {
  680.                 macintoshErr = myerr;
  681.                 Tcl_AppendResult(interp, "\"", argv[0], "\" PBOpenWD() ",
  682.                                         Tcl_MacError(interp), (char *) NULL);
  683.                 return TCL_ERROR;
  684.                 }
  685.             }
  686.         }
  687.  
  688.     return TCL_OK;
  689. #else
  690.     char            temp[256], *ptr;
  691.     FSSpec            spec;
  692.     Boolean            folder, aliased;
  693.     WDPBRec            param;
  694.     int                ups, i;
  695.     
  696.     if (argc > 2) 
  697.     {
  698.         Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  699.                     " dirName\"", (char *) NULL);
  700.         return TCL_ERROR;
  701.     }
  702.  
  703. /* Note that one could support home directories by simply querying an
  704.     environment variable called HOME
  705. */
  706.     if (argc == 1)
  707.     {
  708.         Tcl_SetResult(interp, "ERROR: No home directories on the Mac\r", TCL_STATIC);
  709.         return TCL_ERROR;
  710.     }
  711.     
  712.     // Use the spec to resolve '::' tangles.
  713.     strcpy(temp, argv[1]);
  714.     if (!(*temp)) {
  715.         Tcl_SetResult(interp, "ERROR: No home directories on the Mac\r", TCL_STATIC);
  716.         return TCL_ERROR;
  717.     }
  718.     CtoPstr(temp);
  719.  
  720.   setVol:
  721.     if (FSMakeFSSpec(0, 0, temp, &spec) ||
  722.         ResolveAliasFile(&spec, TRUE, &folder, &aliased))
  723.     {
  724.         Tcl_SetResult(interp, "ERROR: Invalid directory\r", TCL_STATIC);
  725.         return TCL_ERROR;
  726.     }
  727.     param.ioCompletion = NULL;
  728.     param.ioNamePtr = spec.name;
  729.     param.ioVRefNum = spec.vRefNum;
  730.     param.ioWDDirID = spec.parID;
  731.     param.ioWDProcID = 'ERIK';
  732.     if (PBOpenWD(¶m, FALSE)) 
  733.     {
  734.         Tcl_SetResult(interp, "Not a directory", TCL_STATIC);
  735.         return TCL_ERROR;
  736.     }
  737.     if (SetVol("", param.ioVRefNum))
  738.     {
  739.         Tcl_SetResult(interp, "SetVol Failed", TCL_STATIC);
  740.         return TCL_ERROR;
  741.     }
  742.     
  743.     _current_working_directory = param.ioVRefNum;
  744.     _current_working_vrefnum = param.ioWDVRefNum;
  745.     _current_working_dirid = param.ioWDDirID;
  746.     return TCL_OK;
  747.  
  748. #endif
  749.  
  750.     }
  751.  
  752. set_current_wd(vRefNum, dirID)
  753. int        vRefNum;
  754. long    dirID;
  755.     {
  756.     int            myerr;
  757.     WDPBRec        wpb;
  758.  
  759.     wpb.ioCompletion = 0;
  760.     wpb.ioVRefNum = vRefNum;
  761.     wpb.ioNamePtr = (unsigned char *) NULL;
  762.     wpb.ioWDDirID = dirID;
  763.     myerr = PBHSetVol(&wpb, FALSE);
  764.     if (myerr != noErr) {
  765.         return myerr;
  766.         }
  767.     else {
  768.         wpb.ioWDProcID = 'ERIK';
  769.         myerr = PBOpenWD(&wpb, FALSE);
  770.         if (myerr == noErr) {
  771.             _current_working_directory = wpb.ioVRefNum;
  772.             _current_working_vrefnum = wpb.ioWDVRefNum;
  773.             _current_working_dirid = dirID;
  774.             }
  775.         else {
  776.             return myerr;
  777.             }
  778.         }
  779.     }
  780.  
  781. int
  782. current_wd()
  783. {
  784.     return _current_working_directory;
  785.     }
  786.  
  787. int
  788. current_vrefnum()
  789. {
  790.     return _current_working_vrefnum;
  791.     }
  792.  
  793. int
  794. current_dirid()
  795. {
  796.     return _current_working_dirid;
  797.     }
  798.  
  799. int
  800. Cmd_DoPWD(clientData, interp, argc, argv)
  801. char        *clientData;
  802. Tcl_Interp    *interp;
  803. int            argc;
  804. char        **argv;
  805. {
  806. char    path[256];
  807. #pragma unused (clientData, argc, argv)
  808.  
  809. /* Note, the #ifdeffed out version of this command is Tim's original code.
  810.     I've replaced it with my own, which may be no better.  Basically, one
  811.     of the more troublesome parts of porting Tim's code to THINK C was
  812.     the issue of pathnames.  They just didn't seem to work right, so I
  813.     substituted pieces until they did.  Tim's code works fine for him though.
  814. */
  815.  
  816. #ifdef Undefined
  817.     GetPathName(path,NULL,current_vrefnum(),current_dirid());
  818.     p2cstr(path);
  819.     
  820.     Tcl_SetResult(interp, path, TCL_VOLATILE);
  821.  
  822.     return TCL_OK;
  823. #else
  824.     pathname(path, current_wd());
  825.  
  826.     Tcl_SetResult(interp, path, TCL_VOLATILE);
  827.  
  828.     return TCL_OK;
  829. #endif
  830.     }
  831.  
  832. int
  833. Cmd_GetDirectory(clientData, interp, argc, argv)
  834. char        *clientData;
  835. Tcl_Interp    *interp;
  836. int            argc;
  837. char        **argv;
  838. {
  839.  
  840.  
  841. char    path[256];
  842. short    vRefNum;
  843. long    dirID;
  844. #pragma unused (clientData)
  845.  
  846.     SFSaveDisk = current_vrefnum() * -1;
  847.     CurDirStore = current_dirid();
  848.     
  849.     path[0] = '\0';
  850.     if (! GetFolderPathName( ((argc == 2) ? argv[1] : "Directory..."), path, &vRefNum, &dirID ) )
  851.         Tcl_SetResult(interp, "", TCL_VOLATILE);
  852.     else {
  853.         Tcl_SetResult(interp, path, TCL_VOLATILE);
  854.         }
  855.  
  856.     return TCL_OK;
  857.  
  858.     }
  859.  
  860. int
  861. Cmd_GetFile(clientData, interp, argc, argv)
  862. char        *clientData;
  863. Tcl_Interp    *interp;
  864. int            argc;
  865. char        **argv;
  866. {
  867.  
  868.  
  869. char    path[256], prompt[256], *ptr, *ptr2;
  870. int        i, j;
  871. Point    mypoint;
  872. SFReply    myreply;
  873. SFTypeList mytypes;
  874. #pragma unused (clientData, argc, argv)
  875.  
  876.     path[0] = '\0';
  877.     i = -1;
  878.     if (argc > 1) {
  879.         strcpy(prompt, argv[1]);
  880.         c2pstr(prompt);
  881.         }
  882.     if (argc > 2) {
  883.         for (ptr=argv[2],i=0 ; i < 4 && *ptr ; i++) {
  884.             ptr2 = (char *) &mytypes[i];
  885.             for (j=0; j<4; j++) {
  886.                 *ptr2++ = (*ptr) ? *ptr++ : ' ';
  887.                 }
  888.             }
  889.         if (i == 0)
  890.             i = -1;
  891.         }
  892.     
  893.     mypoint.h = mypoint.v = 75;
  894.     
  895.     SFSaveDisk = current_vrefnum() * -1;
  896.     CurDirStore = current_dirid();
  897.     
  898.     MyGetFile(mypoint, prompt, NULL, i, mytypes, NULL, &myreply);
  899.     if (myreply.good) {
  900.         p2cstr(myreply.fName);
  901.         fullname(path, myreply.vRefNum, myreply.fName);
  902.         Tcl_SetResult(interp, path, TCL_VOLATILE);
  903.         }
  904.     else {
  905.         Tcl_SetResult(interp, "", TCL_VOLATILE);
  906.         }
  907.  
  908.     return TCL_OK;
  909.  
  910.     }
  911.  
  912. int
  913. Cmd_PutFile(clientData, interp, argc, argv)
  914. char        *clientData;
  915. Tcl_Interp    *interp;
  916. int            argc;
  917. char        **argv;
  918. {
  919.  
  920.  
  921. char    path[256], prompt[256], original[128];
  922. int        i;
  923. Point    mypoint;
  924. SFReply    myreply;
  925. #pragma unused (clientData, argc, argv)
  926.  
  927.     path[0] = '\0';
  928.     original[0] = '\0';
  929.     i = -1;
  930.     if (argc > 1) {
  931.         strcpy(prompt, argv[1]);
  932.         c2pstr(prompt);
  933.         }
  934.     if (argc > 2) {
  935.         strcpy(original, argv[2]);
  936.         c2pstr(original);
  937.         }
  938.     
  939.     mypoint.h = mypoint.v = 75;
  940.     SFSaveDisk = current_vrefnum() * -1;
  941.     CurDirStore = current_dirid();
  942.     MyPutFile(mypoint, prompt, original, NULL, &myreply);
  943.     if (myreply.good) {
  944.         p2cstr(myreply.fName);
  945.         fullname(path, myreply.vRefNum, myreply.fName);
  946.         Tcl_SetResult(interp, path, TCL_VOLATILE);
  947.         }
  948.     else {
  949.         Tcl_SetResult(interp, "", TCL_VOLATILE);
  950.         }
  951.  
  952.     return TCL_OK;
  953.  
  954.     }
  955.  
  956. space_cnt(str)
  957. char    *str;
  958. {
  959. int        count;
  960.  
  961.     for (count=0 ; *str ; str++)
  962.         if (*str == ' ')
  963.             count++;
  964.     
  965.     return count;
  966.     }
  967.  
  968. int
  969. Cmd_EscapeSpaces(clientData, interp, argc, argv)
  970. char        *clientData;
  971. Tcl_Interp    *interp;
  972. int            argc;
  973. char        **argv;
  974. {
  975. int        i, length;
  976. char    *save, *ptr, *ptr2;
  977. #pragma unused (clientData)
  978.  
  979.     if (argc < 2) {
  980.         Tcl_SetResult(interp, "", TCL_VOLATILE);
  981.         return TCL_OK;
  982.         }
  983.     
  984.     for (length = 0, i = 1 ; i < argc ; i++) {
  985.         length += strlen(argv[i]) + 2;    /* 2 for "\ " */
  986.         length += ( 2 * space_cnt(argv[i]) );
  987.         }
  988.     length += 8;    /* terminator + */
  989.     
  990.     save = ptr = malloc(length);
  991.     if (ptr == NULL) {
  992.         Tcl_AppendResult(interp, "\"", argv[0], "\" out of memory", (char *) NULL);
  993.         return TCL_ERROR;
  994.         }
  995.     else {
  996.         for (length = 0, i = 1 ; i < argc ; i++) {
  997.             if (i > 1) {
  998.                 *ptr++ = '\\';
  999.                 *ptr++ = ' ';
  1000.                 }
  1001.             for (ptr2 = argv[i] ; *ptr2 ; ) {
  1002.                 if (*ptr2 == ' ' && ptr2 > argv[i] && *(ptr2-1) != '\\')
  1003.                     *ptr++ = '\\';
  1004.                 *ptr++ = *ptr2++;
  1005.                 }
  1006.             }
  1007.         
  1008.         *ptr = '\0';
  1009.         Tcl_SetResult(interp, save, TCL_VOLATILE);
  1010.         free(save);
  1011.         }
  1012.  
  1013.     return TCL_OK;
  1014.     }
  1015.  
  1016. int
  1017. Cmd_DoGetenv(clientData, interp, argc, argv)
  1018. char        *clientData;
  1019. Tcl_Interp    *interp;
  1020. int            argc;
  1021. char        **argv;
  1022. {
  1023. char    *ptr;
  1024. extern char * tcl_getenv(char *name);
  1025.  
  1026. #pragma unused (clientData)
  1027.  
  1028.     if (argc != 2) {
  1029.         Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  1030.             " variable_name\"", (char *) NULL);
  1031.         return TCL_ERROR;
  1032.         }
  1033.     else {
  1034.         ptr = tcl_getenv(argv[1]);
  1035. #ifdef NEVER_DEFINED
  1036.         ptr = get_environment(argv[1]);
  1037. #endif
  1038.         if (ptr != NULL)
  1039.             Tcl_SetResult(interp, ptr, TCL_VOLATILE);
  1040.         else
  1041.             Tcl_SetResult(interp, "", TCL_VOLATILE);
  1042.         return TCL_OK;
  1043.         }
  1044.     }
  1045.  
  1046. int
  1047. Cmd_DoPutenv(clientData, interp, argc, argv)
  1048. char        *clientData;
  1049. Tcl_Interp    *interp;
  1050. int            argc;
  1051. char        **argv;
  1052. {
  1053. #pragma unused (clientData)
  1054.  
  1055.     if (argc != 3) {
  1056.         Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  1057.             " name value\"", (char *) NULL);
  1058.         return TCL_ERROR;
  1059.         }
  1060.     else {
  1061.         tcl_setenv(argv[1], argv[2]);
  1062.         Tcl_SetResult(interp, argv[2], TCL_VOLATILE);
  1063.         return TCL_OK;
  1064.         }
  1065.     }
  1066.  
  1067. int
  1068. Cmd_CTime(clientData, interp, argc, argv)
  1069. char        *clientData;
  1070. Tcl_Interp    *interp;
  1071. int            argc;
  1072. char        **argv;
  1073. {
  1074. char    *ptr;
  1075. #ifdef THINK_C
  1076. time_t seconds;
  1077. #else
  1078. unsigned long seconds;
  1079. #endif
  1080. #pragma unused (clientData)
  1081.  
  1082.     if (argc != 2) {
  1083.         Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  1084.             " time\"", (char *) NULL);
  1085.         return TCL_ERROR;
  1086.         }
  1087.     else {
  1088.         char *end;
  1089.         seconds = strtoul(argv[1],&end,10);    /* Tim, I changed this - Eric */
  1090.         ptr = (char *) ctime(&seconds);
  1091.         ptr[strlen(ptr)-1] = '\0';    /* Drop \n */
  1092.         Tcl_SetResult(interp, ptr, TCL_VOLATILE);
  1093.         return TCL_OK;
  1094.         }
  1095.     }
  1096.  
  1097. int
  1098. Cmd_MacDateTime(clientData, interp, argc, argv)
  1099. char        *clientData;
  1100. Tcl_Interp    *interp;
  1101. int            argc;
  1102. char        **argv;
  1103. {
  1104. char            datestr[64], timestr[64];
  1105. unsigned long    now;
  1106. #pragma unused (clientData)
  1107.  
  1108.     if (argc < 2 || argc > 3) {
  1109.         Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  1110.             " time ?format?\" where format is \"long, short, or abbrev\"", (char *) NULL);
  1111.         return TCL_ERROR;
  1112.         }
  1113.     else {
  1114.         if (sscanf(argv[1], "%lu", &now) != 1)
  1115.             {
  1116.             Tcl_AppendResult(interp, "invalid time \"", argv[1], "\"", (char *) NULL);
  1117.             return TCL_ERROR;
  1118.             }
  1119.         else
  1120.             {
  1121.             IUDateString(now, (argc == 2 ? shortDate :
  1122.                                (argv[2][0] == 's' ? shortDate :
  1123.                                 (argv[2][0] == 'l' ? longDate : abbrevDate) ) ), (unsigned char *) datestr);
  1124.             IUTimeString(now, TRUE, (unsigned char *) timestr);
  1125.             p2cstr(datestr);
  1126.             p2cstr(timestr);
  1127.             Tcl_AppendResult(interp, datestr, " ", timestr, (char *) NULL);
  1128.             return TCL_OK;
  1129.             }
  1130.         }
  1131.     }
  1132.  
  1133. int
  1134. Cmd_Ticks(clientData, interp, argc, argv)
  1135. char        *clientData;
  1136. Tcl_Interp    *interp;
  1137. int            argc;
  1138. char        **argv;
  1139. {
  1140. char    tickstr[64];
  1141. #pragma unused (clientData, argv)
  1142.  
  1143.     if (argc != 1) {
  1144.         Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], "\"", (char *) NULL);
  1145.         return TCL_ERROR;
  1146.         }
  1147.     else {
  1148.         sprintf(tickstr, "%lu", TickCount());
  1149.         Tcl_SetResult(interp, tickstr, TCL_VOLATILE);
  1150.         return TCL_OK;
  1151.         }
  1152.     }
  1153.  
  1154. int
  1155. Cmd_Now(clientData, interp, argc, argv)
  1156. char        *clientData;
  1157. Tcl_Interp    *interp;
  1158. int            argc;
  1159. char        **argv;
  1160. {
  1161. unsigned long now;
  1162. char    nowstr[64];
  1163. #pragma unused (clientData, argv)
  1164.  
  1165.     if (argc != 1) {
  1166.         Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], "\"", (char *) NULL);
  1167.         return TCL_ERROR;
  1168.         }
  1169.     else {
  1170.         GetDateTime(&now);
  1171.         sprintf(nowstr, "%lu", now);
  1172.         Tcl_SetResult(interp, nowstr, TCL_VOLATILE);
  1173.         return TCL_OK;
  1174.         }
  1175.     }
  1176.  
  1177. int
  1178. Cmd_AskYesNoCancel(clientData, interp, argc, argv)
  1179. char        *clientData;
  1180. Tcl_Interp    *interp;
  1181. int            argc;
  1182. char        **argv;
  1183. {
  1184. int            result;
  1185. #pragma unused (clientData, argc)
  1186.     
  1187.     UInitCursor();
  1188.     c2pstr(argv[1]);
  1189.     ParamText(argv[1], NULL, NULL, NULL);
  1190.     result = Alert(1015, (ModalFilterProcPtr)/*0*/UniversalFilter);
  1191.     p2cstr(argv[1]);
  1192.     if (result == 1) {
  1193.         Tcl_SetResult(interp, "yes", TCL_VOLATILE);
  1194.         }
  1195.     else if (result == 2) {
  1196.         Tcl_SetResult(interp, "no", TCL_VOLATILE);
  1197.         }
  1198.     else if (result == 3) {
  1199.         Tcl_SetResult(interp, "cancel", TCL_VOLATILE);
  1200.         }
  1201.     return TCL_OK;
  1202.     }
  1203.  
  1204. int
  1205. Cmd_GetInputLine(clientData, interp, argc, argv)
  1206. char        *clientData;
  1207. Tcl_Interp    *interp;
  1208. int            argc;
  1209. char        **argv;
  1210. {
  1211. DialogPtr    myDialog;
  1212. short        itemhit;
  1213. char        mystr[256];
  1214. #pragma unused (clientData, argc)
  1215.  
  1216.     UInitCursor();
  1217.     myDialog = GetNewDialog(2007, NULL, (WindowPtr)-1);
  1218.     if (myDialog == NULL) {
  1219.         Tcl_AppendResult(interp, "\"", argv[0], "\" can not load dialog 2007", (char *) NULL);
  1220.         return TCL_ERROR;
  1221.         }
  1222.     
  1223.     if (argc > 1)
  1224.         MySetText(myDialog, 3, argv[1]);
  1225.         
  1226.     if (argc > 2) {
  1227.         MySetText(myDialog, 4, argv[2]);
  1228.         SelIText(myDialog, 4, 0, 1023);
  1229.         }
  1230.     
  1231.     for ( ; ; ) {
  1232.         SetPort(myDialog);
  1233.         FrameButton(myDialog, ok);
  1234.         ModalDialog((ModalFilterProcPtr)/*0*/UniversalFilter, &itemhit);
  1235.         if (itemhit == ok) {
  1236.             MyGetText(myDialog, 4, mystr);
  1237.             Tcl_SetResult(interp, mystr, TCL_VOLATILE);
  1238.             break;
  1239.             }
  1240.         else if (itemhit == cancel) {
  1241.             Tcl_SetResult(interp, "", TCL_VOLATILE);
  1242.             break;
  1243.             }
  1244.         }
  1245.     
  1246.     CloseDialog(myDialog);
  1247.     return TCL_OK;
  1248.     }
  1249.  
  1250. int
  1251. Cmd_GetFileInfo(clientData, interp, argc, argv)
  1252. char        *clientData;
  1253. Tcl_Interp    *interp;
  1254. int            argc;
  1255. char        **argv;
  1256. {
  1257. char    buffer1[64];
  1258. char    buffer2[64];
  1259. char    buffer3[64];
  1260. char    buffer4[64];
  1261. char    pascal_name[256];
  1262. DateTimeRec    cdate, mdate;
  1263. ParamBlockRec    pb;
  1264. #pragma unused (clientData, argc)
  1265.  
  1266.     strcpy(pascal_name, argv[1]);
  1267.     c2pstr(pascal_name);
  1268.     
  1269.     pb.fileParam.ioCompletion = 0;
  1270.     pb.fileParam.ioVRefNum = current_wd();
  1271.     pb.fileParam.ioNamePtr = (unsigned char *) pascal_name;
  1272.     pb.fileParam.ioFDirIndex = 0;
  1273.     pb.fileParam.ioFVersNum = 0;
  1274.     PBGetFInfo(&pb, FALSE);
  1275.     if (pb.fileParam.ioResult != noErr) {
  1276.         char    msg[64];
  1277.         
  1278.         sprintf(msg, "error #%d in PBGetInfo(%.32s)", pb.fileParam.ioResult, argv[1]);
  1279.         Tcl_AppendResult(interp, "\"", argv[0], "\" ", msg, (char *) NULL);
  1280.         return TCL_ERROR;
  1281.         }
  1282.     else {
  1283.         Secs2Date(pb.fileParam.ioFlCrDat, &cdate);
  1284.         Secs2Date(pb.fileParam.ioFlMdDat, &mdate);
  1285.         sprintf(buffer1, "'%4.4s' '%4.4s' %c%c%c%c%c%c%c",
  1286.                     &pb.fileParam.ioFlFndrInfo.fdCreator, &pb.fileParam.ioFlFndrInfo.fdType,
  1287.                     ( ((pb.fileParam.ioFlFndrInfo.fdFlags&0x8000)!=0)        ? 'L' : 'l' ),
  1288.                     ( ((pb.fileParam.ioFlFndrInfo.fdFlags&fInvisible)!=0)    ? 'V' : 'v' ),
  1289.                     ( ((pb.fileParam.ioFlFndrInfo.fdFlags&fHasBundle)!=0)    ? 'B' : 'b' ),
  1290.                     ( ((pb.fileParam.ioFlFndrInfo.fdFlags&0x1000)!=0)        ? 'S' : 's' ),
  1291.                     ( ((pb.fileParam.ioFlFndrInfo.fdFlags&0x0100)!=0)        ? 'I' : 'i' ),
  1292.                     ( ((pb.fileParam.ioFlFndrInfo.fdFlags&fOnDesk)!=0)        ? 'D' : 'd' ),
  1293.                     ( ((pb.fileParam.ioFlFndrInfo.fdFlags&0x0080)!=0)        ? 'M' : 'm' )                    
  1294.                     );
  1295.         sprintf(buffer2, "%02d/%02d/%02d %02d:%02d:%02d",
  1296.                     cdate.month, cdate.day, cdate.year%100, cdate.hour, cdate.minute, cdate.second
  1297.                     );
  1298.         sprintf(buffer3, "%02d/%02d/%02d %02d:%02d:%02d",
  1299.                     mdate.month, mdate.day, mdate.year%100, mdate.hour, mdate.minute, mdate.second
  1300.                     );
  1301.         sprintf(buffer4, "%d,%d %ld %ld",
  1302.                     pb.fileParam.ioFlFndrInfo.fdLocation.h,
  1303.                     pb.fileParam.ioFlFndrInfo.fdLocation.v,
  1304.                     pb.fileParam.ioFlLgLen, pb.fileParam.ioFlRLgLen
  1305.                     );
  1306.         
  1307.         sprintf(pascal_name, "%s %s %s %s", buffer1, buffer2, buffer3, buffer4);
  1308.         Tcl_SetResult(interp, pascal_name, TCL_VOLATILE);
  1309.         
  1310.         return TCL_OK;
  1311.         }
  1312.     }
  1313.  
  1314. int
  1315. Cmd_SetFileInfo(clientData, interp, argc, argv)
  1316. char        *clientData;
  1317. Tcl_Interp    *interp;
  1318. int            argc;
  1319. char        **argv;
  1320. {
  1321. char    *ptr;
  1322. int        i, j;
  1323. char    pascal_name[256];
  1324. ParamBlockRec    pb;
  1325. #pragma unused (clientData)
  1326.  
  1327.     strcpy(pascal_name, argv[1]);
  1328.     c2pstr(pascal_name);
  1329.     
  1330.     pb.fileParam.ioCompletion = 0;
  1331.     pb.fileParam.ioVRefNum = current_wd();
  1332.     pb.fileParam.ioNamePtr = (unsigned char *) pascal_name;
  1333.     pb.fileParam.ioFDirIndex = 0;
  1334.     pb.fileParam.ioFVersNum = 0;
  1335.     PBGetFInfo(&pb, FALSE);
  1336.     if (pb.fileParam.ioResult != noErr) {
  1337.         char    msg[64];
  1338.         
  1339.         sprintf(msg, "error #%d in PBGetInfo(%.32s)", pb.fileParam.ioResult, argv[1]);
  1340.         Tcl_AppendResult(interp, "\"", argv[0], "\" ", msg, (char *) NULL);
  1341.         return TCL_ERROR;
  1342.         }
  1343.     else {
  1344.         for (i = 2 ; i < argc ; i+=2) {
  1345.             if (argv[i][0] == '-') {
  1346.                 switch (argv[i][1]) {
  1347.                     case 'a':    /* attributes (lowercase = 0, uppercase = 1) [*] */
  1348.                         ptr = argv[i+1];
  1349.                         for (ptr = argv[i+1] ; *ptr ; ptr++) {
  1350.                             switch (*ptr) {
  1351.                                 case 'L': case 'l':    /* Locked / Not */
  1352.                                     if (*ptr == 'L')
  1353.                                         pb.fileParam.ioFlFndrInfo.fdFlags |= 0x8000;
  1354.                                     else
  1355.                                         pb.fileParam.ioFlFndrInfo.fdFlags &= ~0x8000;
  1356.                                     break;
  1357.                                 case 'V': case 'v':    /* Invisible / Visible */
  1358.                                     if (*ptr == 'V')
  1359.                                         pb.fileParam.ioFlFndrInfo.fdFlags |= fInvisible;
  1360.                                     else
  1361.                                         pb.fileParam.ioFlFndrInfo.fdFlags &= ~fInvisible;
  1362.                                     break;
  1363.                                 case 'B': case 'b':    /* Bundled / Not */
  1364.                                     if (*ptr == 'B')
  1365.                                         pb.fileParam.ioFlFndrInfo.fdFlags |= fHasBundle;
  1366.                                     else
  1367.                                         pb.fileParam.ioFlFndrInfo.fdFlags &= ~fHasBundle;
  1368.                                     break;
  1369.                                 case 'S': case 's':    /* System / Not */
  1370.                                     if (*ptr == 'S')
  1371.                                         pb.fileParam.ioFlFndrInfo.fdFlags |= 0x1000;
  1372.                                     else
  1373.                                         pb.fileParam.ioFlFndrInfo.fdFlags &= ~0x1000;
  1374.                                     break;
  1375.                                 case 'I': case 'i':    /* Inited / Not */
  1376.                                     if (*ptr == 'I')
  1377.                                         pb.fileParam.ioFlFndrInfo.fdFlags |= 0x0100;
  1378.                                     else
  1379.                                         pb.fileParam.ioFlFndrInfo.fdFlags &= ~0x0100;
  1380.                                     break;
  1381.                                 case 'D': case 'd':    /* 0x0001 Desktop / Not */
  1382.                                     if (*ptr == 'D')
  1383.                                         pb.fileParam.ioFlFndrInfo.fdFlags |= fOnDesk;
  1384.                                     else
  1385.                                         pb.fileParam.ioFlFndrInfo.fdFlags &= ~fOnDesk;
  1386.                                     break;
  1387.                                 case 'M': case 'm':    /* Sharable / Not */
  1388.                                     if (*ptr == 'M')
  1389.                                         pb.fileParam.ioFlFndrInfo.fdFlags |= 0x0080;
  1390.                                     else
  1391.                                         pb.fileParam.ioFlFndrInfo.fdFlags &= ~0x0080;
  1392.                                     break;
  1393.                                 case 'Z': case 'z':    /* Always Switch / Do Not */
  1394. #ifdef NEVER_DEFINED
  1395.                                     if (*ptr == 'Z')
  1396.                                         pb.fileParam.ioFlFndrInfo.fdFlags |= fHasBundle;
  1397.                                     else
  1398.                                         pb.fileParam.ioFlFndrInfo.fdFlags &= ~fHasBundle;
  1399. #endif
  1400.                                     break;
  1401.                                 }
  1402.                             }
  1403.                         break;
  1404.                     case 'c':    /* file creator */
  1405.                         ptr = (char *) &pb.fileParam.ioFlFndrInfo.fdCreator;
  1406.                         for (j = 0 ; argv[i+1][j] ; j++)
  1407.                             *ptr++ = argv[i+1][j];
  1408.                         for ( ; j < 4 ; j++)
  1409.                             *ptr++ = ' ';
  1410.                         break;
  1411.                     case 'd':    /* creation date (mm/dd/yy [hh:mm[:ss] [AM | PM]]) [*] */
  1412.                         break;
  1413.                     case 'l':    /* ICON location (horizontal,vertical) [*] */
  1414.                         break;
  1415.                     case 'm':    /* modification date (mm/dd/yy [hh:mm[:ss] [AM | PM]]) [*] */
  1416.                         break;
  1417.                     case 't':    /* file type */
  1418.                         ptr = (char *) &pb.fileParam.ioFlFndrInfo.fdType;
  1419.                         for (j = 0 ; argv[i+1][j] ; j++)
  1420.                             *ptr++ = argv[i+1][j];
  1421.                         for ( ; j < 4 ; j++)
  1422.                             *ptr++ = ' ';
  1423.                         break;
  1424.                     }
  1425.                 }
  1426.             else {
  1427.                 Tcl_AppendResult(interp, "\"", argv[0], "\" invalid option ",
  1428.                                         argv[1], (char *) NULL);
  1429.                 return TCL_ERROR;
  1430.                 }
  1431.             }
  1432.         
  1433.         PBSetFInfo(&pb, FALSE);
  1434.         if (pb.fileParam.ioResult != noErr) {
  1435.             char    msg[64];
  1436.             
  1437.             sprintf(msg, "error #%d in PBSetInfo(%.32s)", pb.fileParam.ioResult, argv[1]);
  1438.             Tcl_AppendResult(interp, "\"", argv[0], "\" ", msg, (char *) NULL);
  1439.             return TCL_ERROR;
  1440.             }
  1441.         }
  1442.     
  1443.     return TCL_OK;
  1444.     }
  1445.  
  1446. /* CUSTOM You must write your own application specific version of Cmd_TclMacYield.
  1447.     Tim's version is presented here.  I have ifdeffed it out in favor of a
  1448.     Harvest C-specific version.  You must provide something else.
  1449. */
  1450.  
  1451. #ifdef TEMP_GONE
  1452. int
  1453. Cmd_TclMacYield(clientData, interp, argc, argv)
  1454. char        *clientData;
  1455. Tcl_Interp    *interp;
  1456. int            argc;
  1457. char        **argv;
  1458. {
  1459. int                got_event;
  1460. short            emask, event_ticks;
  1461. WindowPtr        whichwindow;
  1462. #pragma unused (clientData, interp)
  1463.     
  1464.     /* emask = osMask | activMask | updateMask | mDownMask | keyDownMask; */
  1465.     emask = ( everyEvent & ~(autoKeyMask | keyDownMask) );
  1466.     /* emask = osMask | activMask | updateMask | mDownMask | keyDownMask; */
  1467.     
  1468.     event_ticks = 6;
  1469.     if (argc == 2)
  1470.         {
  1471.         event_ticks = atoi(argv[1]);
  1472.         }
  1473.     
  1474.     if (has_wait_next_event) {
  1475.         got_event =  WaitNextEvent(emask, &gEvent, event_ticks, (RgnHandle)0);
  1476.         }
  1477.     else {
  1478.         SystemTask();
  1479.         got_event = GetNextEvent(emask, &gEvent);
  1480.         }
  1481.     
  1482.     /*
  1483.     ** Has the user done something?
  1484.     */
  1485.     if (got_event) {
  1486.     
  1487.         switch (gEvent.what) {
  1488.             case mouseDown:
  1489.                 switch (FindWindow(gEvent.where, &whichwindow)) {
  1490.                     case inMenuBar:
  1491.                         break;
  1492.                     case inDrag:
  1493.                         break;
  1494.                     case inGoAway:
  1495.                         break;
  1496.                     case inGrow:
  1497.                         break;
  1498.                     case inSysWindow:
  1499.                         SystemClick(&gEvent, whichwindow);
  1500.                         break;
  1501.                     case inContent:
  1502.                         break;
  1503.                     }
  1504.                 gLastDown = gEvent.when;
  1505.                 break;
  1506.             case activateEvt:
  1507.                 wind_parse((WindowPtr) gEvent.message, &gEvent, wActivate);
  1508.                 break;
  1509.             case updateEvt:
  1510.                 wind_parse((WindowPtr) gEvent.message, &gEvent, wUpdate);
  1511.                 break;
  1512.             case MFOSEvent:
  1513.                 switch ((gEvent.message >> 24) & 0x00FF) {    /* high byte of message */
  1514.                     case MFSuspendResumeMessage:    /* suspend/resume is also an activate/deactivate */
  1515.                         in_back_ground = (gEvent.message & MFResumeMask) == 0;
  1516.                         if (! in_back_ground) {
  1517.                             /* RESUME */
  1518.                             TEFromScrap();
  1519.                             WatchCursorOn();
  1520.                             }
  1521.                         else {
  1522.                             /* SUSPEND */
  1523.                             UInitCursor();
  1524.                             }
  1525.                         break;
  1526.                     }
  1527.                 break;
  1528.             default:
  1529.                 break;
  1530.             }
  1531.         
  1532.         gLastEvent = gEvent;
  1533.         }
  1534.     
  1535.     return TCL_OK;
  1536.     }
  1537.  
  1538. #else
  1539. int
  1540. Cmd_TclMacYield(clientData, interp, argc, argv)
  1541. char        *clientData;
  1542. Tcl_Interp    *interp;
  1543. int            argc;
  1544. char        **argv;
  1545. {
  1546.     gApplication->Process1Event();
  1547. }
  1548. #endif
  1549.  
  1550. int
  1551. XTCL_Eval_CallBack(cpb, script_handle, result_handle, stdout_handle)
  1552. XTCLParmBlk    *cpb;
  1553. Handle        script_handle;
  1554. Handle        result_handle;
  1555. Handle        stdout_handle;
  1556. {
  1557.     return Tcl_Interp_Handle(cpb->interp, script_handle, result_handle, stdout_handle);
  1558.     }
  1559.  
  1560. int
  1561. Cmd_CallExternalCMD(clientData, interp, argc, argv)
  1562. char        *clientData;
  1563. Tcl_Interp    *interp;
  1564. int            argc;
  1565. char        **argv;
  1566. {
  1567. Handle        myhandle = NULL,
  1568.             result_handle = NULL;
  1569. int            result = TCL_OK;
  1570. short        saveref, the_refnum = -1, user_ref = -1;
  1571. char        name[256];
  1572. XTCLParmBlk    cbpb;
  1573. #pragma unused (clientData)
  1574.  
  1575.     saveref = CurResFile();
  1576.     if (argv[1][0] == '-' && argv[1][1] == 'f' && argv[1][2] == '\0') {
  1577.         c2pstr(argv[2]);
  1578.         SetVol(NULL, current_wd());
  1579.         user_ref = OpenResFile(argv[2]);
  1580.         p2cstr(argv[2]);
  1581.         if (user_ref == -1) {
  1582.             macintoshErr = ResError();
  1583.             Tcl_AppendResult(interp, "\"", argv[0], "\" OpenResfile(", argv[2], ") ",
  1584.                                     Tcl_MacError(interp), (char *) NULL);
  1585.             return TCL_ERROR;
  1586.             }
  1587.         else
  1588.             the_refnum = user_ref;
  1589.         
  1590.         strcpy(name, argv[3]);
  1591.         argc -= 3;
  1592.         argv += 3;
  1593.         }
  1594.     else {
  1595.         strcpy(name, argv[1]);
  1596.         argc--;
  1597.         argv++;
  1598.         }
  1599.     c2pstr(name);
  1600.  
  1601.     if (user_ref != -1) {
  1602.         UseResFile(user_ref);
  1603.         myhandle = GetNamedResource((ResType)'XTCL', name);
  1604.         }
  1605.     if (myhandle == NULL) {
  1606.         UseResFile(app_refnum);
  1607.         the_refnum = app_refnum;
  1608.         myhandle = GetNamedResource((ResType)'XTCL', name);
  1609.         if (myhandle == NULL && xtcl_refnum != -1) {
  1610.             UseResFile(xtcl_refnum);
  1611.             the_refnum = xtcl_refnum;
  1612.             myhandle = GetNamedResource((ResType)'XTCL', name);
  1613.             }
  1614.         }
  1615.     
  1616.     if (myhandle != NULL) {
  1617.         LoadResource(myhandle);
  1618.         DetachResource(myhandle);
  1619.         
  1620.         result_handle = NewHandle(1);
  1621.         if (result_handle != NULL) {
  1622.             **result_handle = '\0';
  1623.  
  1624.             cbpb.version = XTCL_CB_VERSION;
  1625.             cbpb.result = noErr;
  1626.             cbpb.resultH = result_handle;
  1627.             cbpb.interp = interp;
  1628.             cbpb.eval = XTCL_Eval_CallBack;
  1629.             cbpb.cmdRefNum = the_refnum;
  1630.             cbpb.cmdHandle = myhandle;
  1631.             cbpb.modalproc = UniversalFilter;
  1632.     
  1633.             UseResFile(the_refnum);
  1634.             /* CallXTCL(argc, argv, &cbpb, *myhandle); */
  1635.             
  1636.             HLock(myhandle);
  1637.  
  1638.             (((PFI) (*myhandle)) )(argc, argv, &cbpb);
  1639.  
  1640.             HUnlock(myhandle);
  1641.             
  1642.             UseResFile(saveref);
  1643.  
  1644.             if (*result_handle != NULL && **result_handle != '\0')
  1645.                 {
  1646.                 HLock(result_handle);
  1647.                 Tcl_SetResult(interp, *result_handle, TCL_VOLATILE);
  1648.                 HUnlock(result_handle);
  1649.                 }
  1650.             
  1651.             DisposHandle(result_handle);
  1652.  
  1653.             result = cbpb.result;
  1654.             }
  1655.         else
  1656.             {
  1657.             char    msg[64];
  1658.             
  1659.             sprintf(msg, "error #%d getting result handle", MemError());
  1660.             Tcl_AppendResult(interp, "\"", argv[0], "\" ", msg, (char *) NULL);
  1661.             result = TCL_ERROR;
  1662.             }
  1663.         
  1664.         DisposHandle(myhandle);
  1665.         }
  1666.     else {
  1667.         char    msg[96];
  1668.         
  1669.         sprintf(msg, "error %d:%d:%d loading XTCL '%.*s'",
  1670.                 ResError(), MemError(), xtcl_refnum, name[0], &name[1]);
  1671.         Tcl_AppendResult(interp, "\"", argv[0], "\" ", msg, (char *) NULL);
  1672.         if (user_ref != -1)
  1673.             CloseResFile(user_ref);
  1674.         result = TCL_ERROR;
  1675.         }
  1676.     
  1677.     if (user_ref != -1)
  1678.         CloseResFile(user_ref);
  1679.  
  1680.     UseResFile(saveref);
  1681.     return result;
  1682.     }
  1683.  
  1684. static ListHandle    picklist = NULL;
  1685. static char            string_reply[256];
  1686.  
  1687. #define SetCell(cell, row, column)    { (cell).h = column; (cell).v = row; }
  1688. #define ROW(cell)                     (cell).v
  1689.  
  1690. pascal void
  1691. MacListUpdate(myDialog, myItem)
  1692. DialogPtr        myDialog;
  1693. short            myItem;
  1694. {
  1695. Rect            myrect;
  1696. #pragma unused (myItem)
  1697.  
  1698.     LUpdate(myDialog->visRgn, picklist);
  1699.     myrect = (**(picklist)).rView;
  1700.     InsetRect(&myrect, -1, -1);
  1701.     FrameRect(&myrect);
  1702.     }
  1703.  
  1704. pascal Boolean
  1705. MacListFilter(myDialog, myEvent, myItem)
  1706. DialogPtr        myDialog;
  1707. EventRecord        *myEvent;
  1708. short            *myItem;
  1709. {
  1710. Rect    listrect;
  1711. short    myascii;
  1712. Handle    myhandle;
  1713. Point    mypoint;
  1714. short    mytype;
  1715.  
  1716.     SetPort(myDialog);
  1717.     if (myEvent->what == keyDown) {
  1718.         myascii = myEvent->message % 256;
  1719.         if (myascii == '\015' || myascii == '\003') {    /* This is return or enter... */
  1720.             *myItem = 1;
  1721.             return true;
  1722.             }
  1723.         }
  1724.     else if (myEvent->what == mouseDown) {
  1725.         mypoint = myEvent->where;
  1726.         GlobalToLocal(&mypoint);
  1727.         GetDItem(myDialog, 4, &mytype, &myhandle, &listrect);
  1728.         if (PtInRect(mypoint, &listrect) && picklist != NULL) {
  1729.             if (LClick(mypoint, (short)myEvent->modifiers, picklist)) {
  1730.                 /* User double-clicked in cell... */
  1731.                 *myItem = 1;
  1732.                 return true;
  1733.                 }
  1734.             }
  1735.         }
  1736.     else if (myEvent->what == updateEvt) {
  1737.     /* CUSTOM wind_parse is a tickle specific routine which sends an
  1738.         update or activate event to the current window.  You should
  1739.         provide a substitute for your application.  I have not done so,
  1740.         at least not yet.
  1741.     */
  1742. #ifdef Undefined
  1743.         wind_parse((WindowPtr) myEvent->message, myEvent, wUpdate);
  1744. #endif
  1745.         }
  1746.     else if (myEvent->what == activateEvt) {
  1747.         if (picklist != NULL && (WindowPtr)myEvent->message == myDialog)
  1748.             LActivate((Boolean)((myEvent->modifiers & 0x01) != 0), picklist);
  1749. #ifdef Undefined
  1750.         wind_parse((WindowPtr) myEvent->message, myEvent, wActivate);
  1751. #endif
  1752.         }
  1753.     
  1754.     return false;
  1755.     }
  1756.  
  1757.  
  1758.  
  1759. int
  1760. Cmd_MacListPick(clientData, interp, argc, argv)
  1761. char        *clientData;
  1762. Tcl_Interp    *interp;
  1763. int            argc;
  1764. char        **argv;
  1765. {
  1766. short        itemhit, done, row, result, length;
  1767. DialogPtr    mydialog;
  1768. ListHandle    mylist;
  1769. Cell        mycell;
  1770. short        mytype;
  1771. Handle        myhandle;
  1772. Point        cellsize;
  1773. Rect        listrect, dbounds;
  1774. int            listArgc;
  1775. char        **listArgv;
  1776. #pragma unused (clientData)
  1777.  
  1778.     InitCursor();
  1779.     mydialog = GetNewDialog(3030, NULL, (WindowPtr)-1);
  1780.     if (mydialog == NULL) {
  1781.         Tcl_AppendResult(interp, "\"", argv[0], "\" can not load dialog 3030", (char *) NULL);
  1782.         return TCL_ERROR;
  1783.         }
  1784.     
  1785.     if (argv[1][0] == '-' && argv[1][1] == 'p' && argv[1][2] == '\0') {
  1786.         MySetText(mydialog, 3, argv[2]);
  1787.         argc -= 2;
  1788.         argv += 2;
  1789.         }
  1790.     else {
  1791.         MySetText(mydialog, 3, "Select:");
  1792.         }
  1793.     
  1794.     if (argc != 2)
  1795.         {
  1796.         Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  1797.             " ?-p prompt? itemList\"", (char *) NULL);
  1798.         return TCL_ERROR;
  1799.         }
  1800.     
  1801.     if (Tcl_SplitList (interp, argv[1], &listArgc, &listArgv) != TCL_OK)
  1802.         {
  1803.         return TCL_ERROR;
  1804.         }
  1805.  
  1806.     GetDItem(mydialog, 4, &mytype, &myhandle, &listrect);
  1807.     SetDItem(mydialog, 4, mytype, (Handle)MacListUpdate, &listrect);
  1808.     
  1809.     SetPort(mydialog);
  1810.     InsetRect(&listrect, 1, 1);
  1811.     SetRect(&dbounds, 0, 0, (short)1, (short)0);
  1812.     cellsize.h = (listrect.right - listrect.left);
  1813.     cellsize.v = 17;
  1814.  
  1815.     listrect.right -= 15;
  1816.  
  1817.     picklist = LNew(&listrect, &dbounds, cellsize, (short)0,
  1818.                             mydialog, true, false, (Boolean)0, (Boolean)1);
  1819.     if (picklist == NULL) {
  1820.         DisposDialog(mydialog);
  1821.         Tcl_AppendResult(interp, "\"", argv[0], "\" could not create dialog list", (char *) NULL);
  1822.         ckfree((char *) listArgv);
  1823.         return TCL_ERROR;
  1824.         }
  1825.  
  1826.     mylist = picklist;
  1827.     LDoDraw(FALSE, mylist);
  1828.     
  1829.     for (row=0 ; listArgc > 0 ; row++, listArgc--) {
  1830.         LAddRow(1, row, mylist);
  1831.         SetCell(mycell, (short)row, 0);
  1832.         LSetCell((Ptr)listArgv[row], (short)strlen(listArgv[row]), mycell, mylist);
  1833.         }
  1834.  
  1835.     ckfree((char *) listArgv);
  1836.  
  1837.     LDoDraw(TRUE, mylist);
  1838.     /* CenterWindow(mydialog); */
  1839.     ShowWindow(mydialog);
  1840.     
  1841.     for (done=0; ! done; )    {
  1842.         SetPort(mydialog);
  1843.         FrameButton(mydialog, ok);
  1844.         ModalDialog(MacListFilter, &itemhit);
  1845.         switch (itemhit) {
  1846.             case ok:
  1847.                 SetCell(mycell, 0, 0);
  1848.                 done = 1; result = 0;
  1849.                 if (LGetSelect((short)true, &mycell, picklist)) {
  1850.                     length = 255;
  1851.                     LGetCell(string_reply, &length, mycell, picklist);
  1852.                     string_reply[length] = '\0';
  1853.                     result = 1;
  1854.                     }
  1855.                 break;
  1856.             case cancel:
  1857.                 done = 1; result = 0;
  1858.                 break;
  1859.             }
  1860.  
  1861.         }    /* Modal Loop */
  1862.     
  1863.     if (result) {
  1864.         Tcl_SetResult(interp, string_reply, TCL_VOLATILE);
  1865.         }
  1866.     else {
  1867.         Tcl_SetResult(interp, "", TCL_VOLATILE);
  1868.         }
  1869.     
  1870.     SetPort(mydialog);
  1871.     
  1872.     LDispose(mylist);
  1873.     picklist = (ListHandle)0;
  1874.     DisposDialog(mydialog);
  1875.     
  1876.     return TCL_OK;
  1877.     }
  1878.  
  1879.  
  1880. static Handle        _tcl_Houtput_handle = NULL;
  1881.  
  1882. Handle
  1883. tcl_Houtput_sethdl(handle)
  1884. Handle    handle;
  1885. {
  1886. Handle    result = _tcl_Houtput_handle;
  1887.  
  1888.     _tcl_Houtput_handle = handle;
  1889.     return result;
  1890.     }
  1891.  
  1892. Handle
  1893. tcl_Houtput_gethdl()
  1894. {
  1895.     return _tcl_Houtput_handle;
  1896.     }
  1897.  
  1898. tcl_handle_output(str)
  1899. char    *str;
  1900. {
  1901. long    length;
  1902.  
  1903.     length = GetHandleSize(_tcl_Houtput_handle);
  1904.     SetHandleSize(_tcl_Houtput_handle, length + strlen(str));
  1905.     if (MemError() == noErr) {
  1906.         memcpy( (*_tcl_Houtput_handle + length), str, strlen(str) );
  1907.         }
  1908.         
  1909.     }
  1910.  
  1911. int
  1912. Tcl_Interp_Handle(interp, script_handle, result_handle, stdout_handle)
  1913. Tcl_Interp    *interp;
  1914. Handle        script_handle;
  1915. Handle        result_handle;
  1916. Handle        stdout_handle;
  1917. {
  1918. int        result;
  1919. PFI        saveproc;
  1920. Handle    saveH, myhandle = NULL;
  1921. char    result_str[64]/*, *save, *ptr*/;
  1922.  
  1923.     if (stdout_handle == NULL)
  1924.         {
  1925.         myhandle = NewHandle(0);
  1926.         if (myhandle == NULL)
  1927.             {
  1928.             Feedback("Error #%d allocating a stdout handle.", MemError());
  1929.             return -1770;
  1930.             }
  1931.         else
  1932.             saveH = tcl_Houtput_sethdl(myhandle);
  1933.         }
  1934.     else
  1935.         saveH = tcl_Houtput_sethdl(stdout_handle);
  1936.  
  1937.     saveproc = Tcl_SetPrintProcedure(tcl_handle_output);
  1938.     
  1939.     HLock(script_handle);
  1940.     
  1941.     result = Tcl_RecordAndEval(interp, *script_handle, 0);
  1942.  
  1943. #ifdef NEVER_DEFINED
  1944.     ptr = save = *script_handle;
  1945.     for ( ; *ptr ; )
  1946.         {
  1947.         int        savech;
  1948.         
  1949.         for ( ; *ptr && *ptr != '\n' ; ptr++)
  1950.             ;
  1951.         savech = *ptr;
  1952.         *ptr = '\0';
  1953.         
  1954.         result = Tcl_RecordAndEval(interp, save, 0);
  1955.         if (result != TCL_OK)
  1956.             break;
  1957.         
  1958.         if (savech == '\0')
  1959.             break;
  1960.         
  1961.         *ptr++ = savech;
  1962.         save = ptr;
  1963.         }
  1964. #endif
  1965.     
  1966.     HUnlock(script_handle);
  1967.         
  1968.     if (result != TCL_OK) {
  1969.         sprintf(result_str, "\015# Result = %d.\015", result);
  1970.         tcl_handle_output(result_str);
  1971.         tcl_handle_output("# ");
  1972.         tcl_handle_output(interp->result);
  1973.         }
  1974.     else if (interp->result[0] != '\0' && result_handle != NULL)
  1975.         {
  1976.         tcl_Houtput_sethdl(result_handle);
  1977.         tcl_handle_output(interp->result);
  1978.         }
  1979.     
  1980.     Tcl_SetPrintProcedure(saveproc);
  1981.     tcl_Houtput_sethdl(saveH);
  1982.     
  1983.     if (myhandle != NULL)
  1984.         DisposHandle(myhandle);
  1985.         
  1986.     return result;
  1987.     }
  1988.  
  1989.  
  1990. compute_path_dirid(path)
  1991. char    *path;
  1992.     {
  1993.     char        *ptr, *eptr;
  1994.     int            myerr, need_move = 0, need_rename = 0, got_end = 0;
  1995.     char        pascal_name[256];
  1996.     short        vrefnum;
  1997.     long        dirid;
  1998.     CInfoPBRec        cpb;
  1999.     ParamBlockRec    pb;
  2000.     
  2001.     dirid = current_dirid();
  2002.     vrefnum = current_vrefnum();
  2003.     
  2004.     ptr = path;
  2005.     
  2006.     eptr = strchr(ptr, ':');
  2007.     if (eptr != NULL && *ptr != ':') {    /* Full Path Name */
  2008.         dirid = 2;
  2009.         strncpy(&pascal_name[1], ptr, (eptr - ptr) + 1);
  2010.         pascal_name[0] = (int) ((eptr - ptr) + 1);
  2011.  
  2012.         pb.volumeParam.ioCompletion = 0;
  2013.         pb.volumeParam.ioNamePtr = (unsigned char *) pascal_name;
  2014.         pb.volumeParam.ioVRefNum = 0;
  2015.         pb.volumeParam.ioVolIndex = -1;
  2016.         myerr = PBGetVInfo(&pb, FALSE);
  2017.         if (myerr == noErr)
  2018.             vrefnum = pb.volumeParam.ioVRefNum;
  2019.         ptr = eptr + 1;
  2020.         }
  2021.     else if (*ptr == ':')
  2022.         ptr++;
  2023.  
  2024.     cpb.hFileInfo.ioCompletion = 0;
  2025.     cpb.hFileInfo.ioNamePtr = (unsigned char *) pascal_name;
  2026.     cpb.hFileInfo.ioVRefNum = vrefnum;
  2027.     cpb.hFileInfo.ioFDirIndex = 0;
  2028.     cpb.hFileInfo.ioDirID = dirid;
  2029.     for ( ; *ptr ; )
  2030.         {
  2031.         eptr = strchr(ptr, ':');
  2032.         if (eptr != NULL)
  2033.             {
  2034.             strncpy(&pascal_name[1], ptr, (eptr - ptr));
  2035.             pascal_name[0] = (int) (eptr - ptr);
  2036.             }
  2037.         else
  2038.             {
  2039.             break;
  2040.             }
  2041.         myerr = PBGetCatInfo(&cpb, FALSE);
  2042.         Feedback("compute_path_dirid: GetCat()=%d '%.*s' dirid %ld -> %ld, vRef %d ",
  2043.                     myerr, pascal_name[0], &pascal_name[1], dirid, cpb.hFileInfo.ioDirID, vrefnum);
  2044.         if (myerr != noErr)
  2045.             break;
  2046.         dirid = cpb.hFileInfo.ioDirID;
  2047.         ptr = eptr + 1;
  2048.         }
  2049.     
  2050.     return dirid;
  2051.     }
  2052.  
  2053. compute_path_vrefnum(path)
  2054. char    *path;
  2055.     {
  2056.     int                myerr;
  2057.     char            *ptr, volname[64];
  2058.     ParamBlockRec    pb;
  2059.     
  2060.     ptr = strchr(path, ':');
  2061.     if (ptr == NULL)
  2062.         return current_vrefnum();
  2063.     
  2064.     strncpy(&volname[1], path, (ptr - path) + 1);
  2065.     volname[0] = (ptr - path) + 1;
  2066.  
  2067.     pb.volumeParam.ioCompletion = 0;
  2068.     pb.volumeParam.ioNamePtr = (unsigned char *) volname;
  2069.     pb.volumeParam.ioVRefNum = 0;
  2070.     pb.volumeParam.ioVolIndex = -1;
  2071.     myerr = PBGetVInfo(&pb, FALSE);
  2072.     if (myerr == noErr)
  2073.         return pb.volumeParam.ioVRefNum;
  2074.  
  2075.     return current_vrefnum();
  2076.     }
  2077.  
  2078. int
  2079. Cmd_ReMoveFile(clientData, interp, argc, argv)
  2080. char        *clientData;
  2081. Tcl_Interp    *interp;
  2082. int            argc;
  2083. char        **argv;
  2084. {
  2085. int            myerr;
  2086. short        vrefnum;
  2087. long        dirid;
  2088. char        *ptr1, savech, *namep;
  2089. char        pascal_name[64];
  2090. HParamBlockRec    pb;
  2091. #pragma unused (clientData)
  2092.  
  2093.     if (argc != 2) {
  2094.         Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  2095.                             " fileName\"", (char *) NULL);
  2096.         return TCL_ERROR;
  2097.         }
  2098.  
  2099.     namep = argv[1];
  2100.     dirid = current_dirid();
  2101.     vrefnum = current_vrefnum();
  2102.     ptr1 = strrchr(namep, ':');
  2103.     
  2104.     if (ptr1 != NULL) {
  2105.         savech = *(ptr1+1);
  2106.         *(ptr1+1) = '\0';
  2107.         dirid = compute_path_dirid(namep);
  2108.         *(ptr1+1) = savech;
  2109.         strcpy(pascal_name, ptr1 + 1);
  2110.         vrefnum = compute_path_vrefnum(namep);
  2111.         }
  2112.     else
  2113.         strcpy(pascal_name, namep);
  2114.     
  2115.     c2pstr(pascal_name);
  2116.     pb.fileParam.ioCompletion = 0;
  2117.     pb.fileParam.ioNamePtr = (unsigned char *) pascal_name;
  2118.     pb.fileParam.ioVRefNum = vrefnum;
  2119.     pb.fileParam.ioDirID = dirid;
  2120.     myerr = PBHDelete(&pb, FALSE);
  2121.     if (myerr != noErr)
  2122.         {
  2123.         macintoshErr = myerr;
  2124.         Tcl_AppendResult(interp, "\"", argv[0], "\" ", "error deleting \"",
  2125.                         argv[1], "\" ", Tcl_MacError(interp), (char *) NULL);
  2126.         return TCL_ERROR;
  2127.         }
  2128.     
  2129.     return TCL_OK;
  2130.     }
  2131.  
  2132. int
  2133. Cmd_MoveFile(clientData, interp, argc, argv)
  2134. char        *clientData;
  2135. Tcl_Interp    *interp;
  2136. int            argc;
  2137. char        **argv;
  2138. {
  2139. int            myerr, need_move = 0, need_rename = 0, force = 0;
  2140. short        from_vrefnum;
  2141. long        from_dirid, to_dirid;
  2142. char        *ptr1, *ptr2, savech, *oldname, *newname;
  2143. char        pascal_name[64], from_name[64], to_name[64];
  2144. HParamBlockRec    pb;
  2145. CMovePBRec        mpb;
  2146. #pragma unused (clientData)
  2147.  
  2148.     if (argc < 3 || argc > 4) {
  2149.         Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  2150.             " oldName newName ?force?\"", (char *) NULL);
  2151.         return TCL_ERROR;
  2152.         }
  2153.  
  2154.     if (argc == 4)
  2155.         {
  2156.         if (strcmp(argv[3], "force")) {
  2157.             Tcl_AppendResult(interp, "wrong parameter \"", argv[3], "\" : should be \"", argv[0],
  2158.                 " oldName newName ?force?\"", (char *) NULL);
  2159.             return TCL_ERROR;
  2160.             }
  2161.         
  2162.         force = 1;
  2163.         }
  2164.  
  2165.     oldname = argv[1];
  2166.     newname = argv[2];
  2167.  
  2168.     to_dirid = current_dirid();
  2169.     from_dirid = current_dirid();
  2170.     
  2171.     from_vrefnum = current_vrefnum();
  2172.     
  2173.     ptr1 = strrchr(oldname, ':');
  2174.     ptr2 = strrchr(newname, ':');
  2175.     
  2176.     if (ptr1 != NULL) {
  2177.         savech = *(ptr1+1);
  2178.         *(ptr1+1) = '\0';
  2179.         from_dirid = compute_path_dirid(oldname);
  2180.         *(ptr1+1) = savech;
  2181.         strcpy(from_name, ptr1 + 1);
  2182.         from_vrefnum = compute_path_vrefnum(oldname);
  2183.         }
  2184.     else
  2185.         strcpy(from_name, oldname);
  2186.         
  2187.     if (ptr2 != NULL) {
  2188.         savech = *(ptr2+1);
  2189.         *(ptr2+1) = '\0';
  2190.         to_dirid = compute_path_dirid(newname);
  2191.         *(ptr2+1) = savech;
  2192.         strcpy(to_name, ptr2 + 1);
  2193.         from_vrefnum = compute_path_vrefnum(newname);
  2194.         }
  2195.     else
  2196.         strcpy(to_name, newname);
  2197.         
  2198.     if (ptr1 != NULL || ptr2 != NULL)
  2199.         {
  2200.         need_move = 1;
  2201.         if (ptr1 != NULL && ptr2 != NULL) {
  2202.             *ptr1 = '\0';
  2203.             *ptr2 = '\0';
  2204.             if (strcmp(oldname, newname) == 0)
  2205.                 need_move = 0;
  2206.             *ptr1 = ':';
  2207.             *ptr2 = ':';
  2208.             }
  2209.         }
  2210.         
  2211.     if (strcmp(from_name, to_name) != 0)
  2212.         need_rename = 1;
  2213.  
  2214.     if (need_move)
  2215.         {
  2216.         strcpy(pascal_name, from_name);
  2217.         c2pstr(pascal_name);
  2218.         
  2219. retry_move:
  2220.         mpb.ioCompletion = 0;
  2221.         mpb.ioNamePtr = (unsigned char *) pascal_name;
  2222.         mpb.ioVRefNum = from_vrefnum;
  2223.         mpb.ioNewName = "\p";
  2224.         mpb.ioNewDirID = to_dirid;
  2225.         mpb.ioDirID = from_dirid;
  2226.         myerr = PBCatMove(&mpb, FALSE);
  2227.         if (myerr != noErr)
  2228.             {
  2229.             if (force && myerr == dupFNErr)
  2230.                 {
  2231.                 pb.fileParam.ioCompletion = 0;
  2232.                 pb.fileParam.ioNamePtr = (unsigned char *) pascal_name;
  2233.                 pb.fileParam.ioVRefNum = from_vrefnum;
  2234.                 pb.fileParam.ioFVersNum = 0;
  2235.                 pb.fileParam.ioDirID = to_dirid;
  2236.                 myerr = PBHDelete(&pb, FALSE);
  2237.                 if (myerr == noErr)
  2238.                     goto retry_move;
  2239.                 }
  2240.             
  2241.             macintoshErr = myerr;
  2242.             Tcl_AppendResult(interp, "\"", argv[0], "\" error moving file ",
  2243.                                 Tcl_MacError(interp), (char *) NULL);
  2244.             return TCL_ERROR;
  2245.             }
  2246.         }
  2247.     
  2248.     if (need_rename)
  2249.         {
  2250.         c2pstr(from_name);
  2251.         c2pstr(to_name);
  2252.  
  2253. retry_rename:
  2254.         pb.ioParam.ioCompletion = 0;
  2255.         pb.ioParam.ioNamePtr = (unsigned char *) from_name;
  2256.         pb.ioParam.ioVRefNum = from_vrefnum;
  2257.         pb.ioParam.ioMisc = to_name;
  2258.         pb.ioParam.ioVersNum = 0;
  2259.         pb.fileParam.ioDirID = to_dirid;
  2260.         myerr = PBHRename(&pb, FALSE);
  2261.         if (myerr != noErr)
  2262.             {
  2263.             if (force && myerr == dupFNErr)
  2264.                 {
  2265.                 pb.fileParam.ioCompletion = 0;
  2266.                 pb.fileParam.ioNamePtr = (unsigned char *) to_name;
  2267.                 pb.fileParam.ioVRefNum = from_vrefnum;
  2268.                 pb.fileParam.ioFVersNum = 0;
  2269.                 pb.fileParam.ioDirID = to_dirid;
  2270.                 myerr = PBHDelete(&pb, FALSE);
  2271.                 if (myerr == noErr)
  2272.                     goto retry_rename;
  2273.                 }
  2274.             macintoshErr = myerr;
  2275.             Tcl_AppendResult(interp, "\"", argv[0], "\" error renaming file ",
  2276.                                 Tcl_MacError(interp), (char *) NULL);
  2277.             return TCL_ERROR;
  2278.             }
  2279.         }
  2280.         
  2281.     return TCL_OK;
  2282.     }
  2283.  
  2284. int
  2285. Cmd_CopyFile(clientData, interp, argc, argv)
  2286. char        *clientData;
  2287. Tcl_Interp    *interp;
  2288. int            argc;
  2289. char        **argv;
  2290. {
  2291. int            myerr, eoferr, need_move = 0, need_rename = 0, force = 0;
  2292. short        from_vrefnum, to_vrefnum, inerr, outerr;
  2293. long        from_dirid, to_dirid;
  2294. char        *ptr1, *ptr2, savech, *oldname, *newname;
  2295. char        from_name[64], to_name[64];
  2296. HParamBlockRec    inparm, outparm;
  2297. #pragma unused (clientData)
  2298.  
  2299.     if (argc < 3 || argc > 4) {
  2300.         Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
  2301.             " fromName toName ?force?\"", (char *) NULL);
  2302.         return TCL_ERROR;
  2303.         }
  2304.  
  2305.     if (argc == 4)
  2306.         {
  2307.         if (strcmp(argv[3], "force")) {
  2308.             Tcl_AppendResult(interp, "wrong parameter \"", argv[3], "\" : should be \"", argv[0],
  2309.                 " oldName newName ?force?\"", (char *) NULL);
  2310.             return TCL_ERROR;
  2311.             }
  2312.         
  2313.         force = 1;
  2314.         }
  2315.  
  2316.     oldname = argv[1];
  2317.     newname = argv[2];
  2318.  
  2319.     to_dirid = current_dirid();
  2320.     from_dirid = current_dirid();
  2321.     
  2322.     to_vrefnum = current_vrefnum();
  2323.     from_vrefnum = current_vrefnum();
  2324.     
  2325.     ptr1 = strrchr(oldname, ':');
  2326.     ptr2 = strrchr(newname, ':');
  2327.     
  2328.     if (ptr1 != NULL) {
  2329.         savech = *(ptr1+1);
  2330.         *(ptr1+1) = '\0';
  2331.         from_dirid = compute_path_dirid(oldname);
  2332.         *(ptr1+1) = savech;
  2333.         strcpy(from_name, ptr1 + 1);
  2334.         from_vrefnum = compute_path_vrefnum(oldname);
  2335.         }
  2336.     else
  2337.         strcpy(from_name, oldname);
  2338.         
  2339.     if (ptr2 != NULL) {
  2340.         savech = *(ptr2+1);
  2341.         *(ptr2+1) = '\0';
  2342.         to_dirid = compute_path_dirid(newname);
  2343.         *(ptr2+1) = savech;
  2344.         strcpy(to_name, ptr2 + 1);
  2345.         to_vrefnum = compute_path_vrefnum(newname);
  2346.         }
  2347.     else
  2348.         strcpy(to_name, newname);
  2349.     
  2350.     c2pstr(from_name);
  2351.     c2pstr(to_name);
  2352.  
  2353.     inparm.ioParam.ioCompletion = 0;
  2354.     inparm.ioParam.ioNamePtr = (unsigned char *) from_name;
  2355.     inparm.ioParam.ioVRefNum = from_vrefnum;
  2356.     inparm.ioParam.ioVersNum = 0;
  2357.     inparm.ioParam.ioPermssn = fsRdPerm;
  2358.     inparm.ioParam.ioMisc = NULL;
  2359.     inparm.fileParam.ioDirID = from_dirid;
  2360.     inerr = PBHOpen(&inparm, FALSE);
  2361.     if (inerr != noErr) {
  2362.         Feedback("DATA OPEN IN: err %d '%.*s' dir %ld vref %d ",
  2363.                     inerr, from_name[0], &from_name[1], from_dirid, from_vrefnum);
  2364.         macintoshErr = inerr;
  2365.         p2cstr(from_name);
  2366.         Tcl_AppendResult(interp, "error opening DATA \"",
  2367.                             from_name, "\" ", Tcl_MacError(interp), (char *) NULL);
  2368.         return TCL_ERROR;
  2369.         }
  2370.  
  2371.     outparm.ioParam.ioCompletion = 0;
  2372.     outparm.ioParam.ioNamePtr = (unsigned char *) to_name;
  2373.     outparm.ioParam.ioVRefNum = to_vrefnum;
  2374.     outparm.ioParam.ioVersNum = 0;
  2375.     outparm.ioParam.ioPermssn = fsWrPerm;
  2376.     outparm.ioParam.ioMisc = NULL;
  2377.     outparm.fileParam.ioDirID = to_dirid;
  2378.     outerr = PBHCreate(&outparm, false);
  2379.     if ( (outerr != noErr && outerr != dupFNErr) ||
  2380.          (outerr == dupFNErr && ! force) )
  2381.         {
  2382.         Feedback("DATA CREATE: err %d '%.*s' dir %ld vref %d ",
  2383.                     outerr, to_name[0], &to_name[1], to_dirid, to_vrefnum);
  2384.         PBClose((ParmBlkPtr)&inparm, false);
  2385.         p2cstr(to_name);
  2386.         macintoshErr = outerr;
  2387.         Tcl_AppendResult(interp, "error creating DATA \"",
  2388.                             to_name, "\" ", Tcl_MacError(interp), (char *) NULL);
  2389.         return TCL_ERROR;
  2390.         }
  2391.     
  2392.     outerr = PBHOpen(&outparm, false);
  2393.     if (outerr != noErr) {
  2394.         Feedback("DATA OPEN: err %d '%.*s' dir %ld vref %d ",
  2395.                     outerr, to_name[0], &to_name[1], to_dirid, to_vrefnum);
  2396.         PBClose((ParmBlkPtr)&inparm, false);
  2397.         p2cstr(to_name);
  2398.         macintoshErr = outerr;
  2399.         Tcl_AppendResult(interp, "error opening DATA \"",
  2400.                             to_name, "\" ", Tcl_MacError(interp), (char *) NULL);
  2401.         return TCL_ERROR;
  2402.         }
  2403.     
  2404.     myerr = CopyFork(&inparm, &outparm);
  2405.  
  2406.     PBGetEOF((ParmBlkPtr)&inparm, FALSE);
  2407.     outparm.ioParam.ioMisc = inparm.ioParam.ioMisc;
  2408.     eoferr = PBSetEOF((ParmBlkPtr)&outparm, FALSE);
  2409.     
  2410.     PBClose((ParmBlkPtr)&inparm, FALSE);
  2411.     PBClose((ParmBlkPtr)&outparm, FALSE);
  2412.     
  2413.     FlushVol(NULL, to_vrefnum);
  2414.  
  2415.     if (myerr != noErr) {
  2416.         p2cstr(to_name);
  2417.         p2cstr(from_name);
  2418.         Tcl_AppendResult(interp, "error copying DATA \"",
  2419.                             from_name, "\" to \"", to_name, "\" ", (char *) NULL);
  2420.         return TCL_ERROR;
  2421.         }
  2422.     
  2423.     if (eoferr != noErr) {
  2424.         macintoshErr = myerr;
  2425.         Tcl_AppendResult(interp, "error setting DATA EOF ", Tcl_MacError(interp), (char *) NULL);
  2426.         return TCL_ERROR;
  2427.         }
  2428.  
  2429.     myerr = PBHOpenRF(&inparm, FALSE);
  2430.     if (myerr != noErr && myerr != eofErr && myerr != fnfErr) {
  2431.         Feedback("RSRC OPEN IN: err %d '%.*s' dir %ld vref %d ",
  2432.                     myerr, from_name[0], &from_name[1], from_dirid, from_vrefnum);
  2433.         macintoshErr = myerr;
  2434.         p2cstr(from_name);
  2435.         Tcl_AppendResult(interp, "error opening RSRC \"",
  2436.                             from_name, "\" ", Tcl_MacError(interp), (char *) NULL);
  2437.         return TCL_ERROR;
  2438.         }
  2439.     else if (myerr == noErr) {
  2440.         myerr = PBHOpenRF(&outparm, false);
  2441.         if (myerr != noErr) {
  2442.             Feedback("RSRC OPEN OUT: err %d '%.*s' dir %ld vref %d ",
  2443.                         myerr, to_name[0], &to_name[1], to_dirid, to_vrefnum);
  2444.             PBClose((ParmBlkPtr)&inparm, FALSE);
  2445.             macintoshErr = myerr;
  2446.             p2cstr(from_name);
  2447.             Tcl_AppendResult(interp, "error opening RSRC \"",
  2448.                                 to_name, "\" ", Tcl_MacError(interp), (char *) NULL);
  2449.             return TCL_ERROR;
  2450.             }
  2451.         
  2452.         myerr = CopyFork(&inparm, &outparm);
  2453.     
  2454.         PBGetEOF((ParmBlkPtr)&inparm, FALSE);
  2455.         outparm.ioParam.ioMisc = inparm.ioParam.ioMisc;
  2456.         eoferr = PBSetEOF((ParmBlkPtr)&outparm, FALSE);
  2457.         
  2458.         PBClose((ParmBlkPtr)&inparm, FALSE);
  2459.         PBClose((ParmBlkPtr)&outparm, FALSE);
  2460.     
  2461.         if (myerr != noErr) {
  2462.             p2cstr(to_name);
  2463.             p2cstr(from_name);
  2464.             Tcl_AppendResult(interp, "error copying RSRC \"",
  2465.                                 from_name, "\" to \"", to_name, "\" ", (char *) NULL);
  2466.             return TCL_ERROR;
  2467.             }
  2468.         if (eoferr != noErr) {
  2469.             macintoshErr = myerr;
  2470.             Tcl_AppendResult(interp, "error setting RSRC EOF ", Tcl_MacError(interp), (char *) NULL);
  2471.             return TCL_ERROR;
  2472.             }
  2473.         }
  2474.     
  2475.     FlushVol(NULL, to_vrefnum);
  2476.  
  2477.     inparm.fileParam.ioCompletion = 0;
  2478.     inparm.fileParam.ioNamePtr = (unsigned char *) from_name;
  2479.     inparm.fileParam.ioVRefNum = from_vrefnum;
  2480.     inparm.fileParam.ioFVersNum = 0;
  2481.     inparm.fileParam.ioDirID = from_dirid;
  2482.     inparm.fileParam.ioFDirIndex = 0;
  2483.     myerr = PBHGetFInfo(&inparm, FALSE);
  2484.     if (myerr == noErr)
  2485.         {
  2486.         outparm.fileParam.ioCompletion = 0;
  2487.         outparm.fileParam.ioNamePtr = (unsigned char *) to_name;
  2488.         outparm.fileParam.ioVRefNum = to_vrefnum;
  2489.         outparm.fileParam.ioFVersNum = 0;
  2490.         outparm.fileParam.ioDirID = to_dirid;
  2491.         outparm.fileParam.ioFDirIndex = 0;
  2492.         outparm.fileParam.ioFlFndrInfo = inparm.fileParam.ioFlFndrInfo;
  2493.         outparm.fileParam.ioFlFndrInfo.fdLocation.h += 16;
  2494.         outparm.fileParam.ioFlFndrInfo.fdLocation.v += 16;
  2495.         GetDateTime(&outparm.fileParam.ioFlCrDat);
  2496.         outparm.fileParam.ioFlMdDat = outparm.fileParam.ioFlCrDat;
  2497.         myerr = PBHSetFInfo(&outparm, FALSE);
  2498.         if (myerr != noErr) {
  2499.             Feedback("SET INFO: err %d '%.*s' dir %ld vref %d ",
  2500.                         myerr, to_name[0], &to_name[1], to_dirid, to_vrefnum);
  2501.             macintoshErr = myerr;
  2502.             Tcl_AppendResult(interp, "error setting INFO ", Tcl_MacError(interp), (char *) NULL);
  2503.             return TCL_ERROR;
  2504.             }
  2505.         }
  2506.     else
  2507.         {
  2508.         Feedback("GET INFO: err %d '%.*s' dir %ld vref %d ",
  2509.                         myerr, from_name[0], &from_name[1], from_dirid, from_vrefnum);
  2510.         macintoshErr = myerr;
  2511.         Tcl_AppendResult(interp, "error getting INFO ", Tcl_MacError(interp), (char *) NULL);
  2512.         return TCL_ERROR;
  2513.         }
  2514.     
  2515.     FlushVol(NULL, to_vrefnum);
  2516.     return TCL_OK;
  2517.     }
  2518.  
  2519. #define    INPARAM        inparm->ioParam
  2520. #define    OUTPARAM    outparm->ioParam
  2521. CopyFork(inparm, outparm)
  2522. ParamBlockRec    *inparm;
  2523. ParamBlockRec    *outparm;
  2524. {
  2525. short done, myerr;
  2526. char mybuffer[512];
  2527.  
  2528.     for (done=false; ! done; ) {
  2529.         inparm->ioParam.ioReqCount = (long)512;
  2530.         inparm->ioParam.ioBuffer = mybuffer;
  2531.         inparm->ioParam.ioPosMode = fsAtMark;
  2532.         
  2533.         myerr = PBRead(inparm, (Boolean)false);
  2534.         
  2535.         if (myerr != noErr && myerr != eofErr)
  2536.             return myerr;
  2537.         if (myerr == eofErr)
  2538.             done = true;
  2539.         
  2540.         outparm->ioParam.ioReqCount = INPARAM.ioActCount;
  2541.         outparm->ioParam.ioBuffer = mybuffer;
  2542.         outparm->ioParam.ioPosMode = fsAtMark;
  2543.         
  2544.         myerr = PBWrite(outparm, (Boolean)false);
  2545.         
  2546.         if (myerr != noErr)
  2547.             return myerr;
  2548.         if (inparm->ioParam.ioActCount != outparm->ioParam.ioActCount) {
  2549.             done = true;
  2550.             }
  2551.         }
  2552.     
  2553.     return noErr;
  2554.     }
  2555.  
  2556. typedef struct {
  2557.     char    *name;
  2558.     char    *value;
  2559.     } environ_entry;
  2560.     
  2561. environ_entry    *environment = NULL;
  2562. int                environ_entries = 0;
  2563. int                environ_allocated = 0;
  2564.  
  2565. init_environment()
  2566. {
  2567. char    *ptr;
  2568. FILE    *infile;
  2569. char    input[512];
  2570. char    filtered[512];
  2571.  
  2572. #ifdef NEVER_DEFINED
  2573.     check_environment_add(32);
  2574. #endif
  2575.     
  2576.     infile = fopen("Ñtclenv", "r");
  2577.     if (infile != NULL) {
  2578.         for ( ; fgets(input, sizeof(input)-1, infile) != NULL ; ) {
  2579. #ifdef THINK_C
  2580.             if (input[strlen(input)-1] == '\r')
  2581.                 input[strlen(input)-1] = '\0';
  2582.             if (input[strlen(input)-1] == '\n')
  2583.                 input[strlen(input)-1] = '\0';
  2584. #endif
  2585.             if (input[strlen(input)-1] == '\015')
  2586.                 input[strlen(input)-1] = '\0';
  2587.             for (ptr=input; *ptr && *ptr != '='; ptr++)
  2588.                 ;
  2589.             if (*ptr == '=') {
  2590.                 *ptr = '\0';
  2591.                 filter_unix_string(filtered, ptr + 1);
  2592.                 tcl_setenv(input, filtered);
  2593.                 *ptr = '=';
  2594.                 }
  2595.             }
  2596.         
  2597.         fclose(infile);
  2598.         }
  2599.     }
  2600.  
  2601. #ifdef NEVER_DEFINED
  2602.  
  2603. put_environment(name, value)
  2604. char    *name;
  2605. char    *value;
  2606. {
  2607.     check_environment_add(1);
  2608.     
  2609.     environment[environ_entries].name = csavestr(name);
  2610.     environment[environ_entries].value = csavestr(value);
  2611.     environ_entries++;
  2612.     
  2613.     check_environment_set_of_globals(name, value);
  2614.     }
  2615.  
  2616. char *
  2617. get_environment(name)
  2618. char    *name;
  2619. {
  2620. int        i;
  2621.  
  2622.     for (i = 0; i < environ_entries; i++)
  2623.         if (StrCmp(environment[i].name, name) == 0)
  2624.             return environment[i].value;
  2625.  
  2626.     return NULL;
  2627.     }
  2628.  
  2629. check_environment_add(num)
  2630. int        num;
  2631. {
  2632. int                new_count;
  2633. environ_entry    *new_entries;
  2634.  
  2635.     if ( (environ_entries + num) >= environ_allocated )
  2636.         {
  2637.         new_count = environ_entries + num + 16;
  2638.         new_entries = (environ_entry *) malloc(new_count * sizeof(environ_entry));
  2639.         if (new_entries != NULL) {
  2640.             memset(new_entries, 0, environ_entries * sizeof(environ_entry));
  2641.             memcpy(new_entries, environment, environ_entries * sizeof(environ_entry));
  2642.             if (environment != NULL)
  2643.                 free(environment);
  2644.             environment = new_entries;
  2645.             environ_allocated = new_count;
  2646.             }
  2647.         else
  2648.             return 0;
  2649.         }
  2650.     
  2651.     return 1;
  2652.     }
  2653.     
  2654. #endif
  2655.  
  2656. list_environment()
  2657. {
  2658. #ifdef NEVER_DEFINED
  2659. int        i;
  2660.  
  2661.     Feedback("Environment has %d entries. %d allocated.", environ_entries, environ_allocated);
  2662.     for (i = 0; i < environ_entries; i++)
  2663.         Feedback("<%s> <%s>", environment[i].name, environment[i].value);
  2664. #endif
  2665.     }
  2666.  
  2667. #ifdef NEVER_DEFINED
  2668.  
  2669. read_default_environment_globals()
  2670.     {
  2671.     char    *ptr;
  2672.     
  2673.     ptr = get_environment("LOGLEVEL");
  2674.     if (ptr != NULL)
  2675.         g_log_level = atoi(ptr);
  2676.  
  2677. #ifdef TCLENGINE
  2678.     ptr = get_environment("ENGINE_NOISE");
  2679.     if (ptr != NULL)
  2680.         {
  2681.         engine_verbosity = atoi(ptr);
  2682.         if (engine_verbosity < 0 || engine_verbosity > 2)
  2683.             engine_verbosity = 1;
  2684.         }
  2685. #endif
  2686.     }
  2687.  
  2688. #endif
  2689.  
  2690. check_environment_set_of_globals(name, value)
  2691. char    *name;
  2692. char    *value;
  2693.     {
  2694.     if (strcmp("CRON_TICKS", name) == 0)
  2695.         {
  2696.         g_cron_interval = atol(value);
  2697.         g_next_cron_time = TickCount() + g_cron_interval;
  2698.         Feedback("Cron ticks now: %ld. Next task time: %ld.",
  2699.                     g_cron_interval, g_next_cron_time);
  2700.         }
  2701.     else if (strcmp("TEXT_CREATOR", name) == 0)
  2702.         {
  2703.         char    tempstr[8];
  2704.         
  2705.         sprintf(tempstr, "%-4.4s", value);
  2706.         memcpy(&def_text_file_creator, tempstr, 4);
  2707.         Feedback("Default text creator now: '%-4.4s'.", &def_text_file_creator);
  2708.         }
  2709.     }
  2710.  
  2711.  
  2712. char *
  2713. csavestr(str)
  2714. char    *str;
  2715. {
  2716. char    *ptr;
  2717.  
  2718.     ptr = malloc(strlen(str) + 1);
  2719.     if (ptr)
  2720.         strcpy(ptr, str);
  2721.     return ptr;
  2722.     }
  2723.  
  2724. Tcl_InitMacintosh(interp)
  2725. Tcl_Interp    *interp;
  2726. {
  2727. int        result;
  2728. char    command[128];
  2729.  
  2730.     Tcl_CreateCommand(interp, "alertnote", Cmd_DoAlertNote,
  2731.                         (ClientData)NULL, (void (*)())NULL);
  2732.     Tcl_CreateCommand(interp, "cd", Cmd_DoCD,
  2733.                         (ClientData)NULL, (void (*)())NULL);
  2734.     Tcl_CreateCommand(interp, "pwd", Cmd_DoPWD,
  2735.                         (ClientData)NULL, (void (*)())NULL);
  2736.     Tcl_CreateCommand(interp, "get_directory", Cmd_GetDirectory,
  2737.                         (ClientData)NULL, (void (*)())NULL);
  2738.     Tcl_CreateCommand(interp, "getenv", Cmd_DoGetenv,
  2739.                         (ClientData)NULL, (void (*)())NULL);
  2740.     Tcl_CreateCommand(interp, "putenv", Cmd_DoPutenv,
  2741.                         (ClientData)NULL, (void (*)())NULL);
  2742.     Tcl_CreateCommand(interp, "xtclcmd", Cmd_CallExternalCMD,
  2743.                         (ClientData)NULL, (void (*)())NULL);
  2744.     Tcl_CreateCommand(interp, "askyesno", Cmd_AskYesNoCancel,
  2745.                         (ClientData)NULL, (void (*)())NULL);
  2746.     Tcl_CreateCommand(interp, "getline", Cmd_GetInputLine,
  2747.                         (ClientData)NULL, (void (*)())NULL);
  2748.     Tcl_CreateCommand(interp, "espace", Cmd_EscapeSpaces,
  2749.                         (ClientData)NULL, (void (*)())NULL);
  2750.     Tcl_CreateCommand(interp, "getfile", Cmd_GetFile,
  2751.                         (ClientData)NULL, (void (*)())NULL);
  2752.     Tcl_CreateCommand(interp, "putfile", Cmd_PutFile,
  2753.                         (ClientData)NULL, (void (*)())NULL);
  2754.     Tcl_CreateCommand(interp, "listpick", Cmd_MacListPick,
  2755.                         (ClientData)NULL, (void (*)())NULL);
  2756.     Tcl_CreateCommand(interp, "feedback", Cmd_Feedback,
  2757.                         (ClientData)NULL, (void (*)())NULL);
  2758.     Tcl_CreateCommand(interp, "getfinfo", Cmd_GetFileInfo,
  2759.                         (ClientData)NULL, (void (*)())NULL);
  2760.     Tcl_CreateCommand(interp, "setfinfo", Cmd_SetFileInfo,
  2761.                         (ClientData)NULL, (void (*)())NULL);
  2762.     Tcl_CreateCommand(interp, "ctime", Cmd_CTime,
  2763.                         (ClientData)NULL, (void (*)())NULL);
  2764.     Tcl_CreateCommand(interp, "mtime", Cmd_MacDateTime,
  2765.                         (ClientData)NULL, (void (*)())NULL);
  2766.     Tcl_CreateCommand(interp, "mv", Cmd_MoveFile,
  2767.                         (ClientData)NULL, (void (*)())NULL);
  2768.     Tcl_CreateCommand(interp, "cp", Cmd_CopyFile,
  2769.                         (ClientData)NULL, (void (*)())NULL);
  2770.     Tcl_CreateCommand(interp, "rm", Cmd_ReMoveFile,
  2771.                         (ClientData)NULL, (void (*)())NULL);
  2772.     Tcl_CreateCommand(interp, "now", Cmd_Now,
  2773.                         (ClientData)NULL, (void (*)())NULL);
  2774.     Tcl_CreateCommand(interp, "ticks", Cmd_Ticks,
  2775.                         (ClientData)NULL, (void (*)())NULL);
  2776.     Tcl_CreateCommand(interp, "yield_mac", Cmd_TclMacYield,
  2777.                         (ClientData)NULL, (void (*)())NULL);
  2778.     
  2779.     Tcl_InitXmath(interp);
  2780.     
  2781.     sprintf(command, "set HARVESTCVERS {%#s}\n", MyVersion);
  2782.     result = Tcl_Eval(interp, command, 0, (char **)0);
  2783.     if (result != TCL_OK)
  2784.         Feedback("ERROR %d on <%s>", result, command);
  2785.         
  2786.     sprintf(command, "set MACINTOSH 1\n");
  2787.     result = Tcl_Eval(interp, command, 0, (char **)0);
  2788.     if (result != TCL_OK)
  2789.         Feedback("ERROR %d on <%s>", result, command);
  2790.         
  2791.     sprintf(command, "set AEVENT 0\n");
  2792.     result = Tcl_Eval(interp, command, 0, (char **)0);
  2793.     if (result != TCL_OK)
  2794.         Feedback("ERROR %d on <%s>", result, command);
  2795.         
  2796.     Tcl_SetPrintProcedure(tcl_print_tclshell);
  2797. }
  2798.  
  2799. static char             message_string[512];
  2800.  
  2801. #define message_note_alert      (short)1010
  2802. #define message_alert_alert     (short)1011
  2803.  
  2804. message_note(format_str, arg0, arg1, arg2, arg3, arg4, arg5)
  2805. char    *format_str;
  2806. long    arg0, arg1, arg2, arg3, arg4, arg5;
  2807. {
  2808. Str255  pascal_name;
  2809.         InitCursor();
  2810.         sprintf(message_string, format_str,
  2811.                         arg0, arg1, arg2, arg3, arg4, arg5);
  2812.         pascal_name[0] = strlen(message_string);
  2813.         strcpy((char *) &pascal_name[1], message_string);
  2814.         ParamText(&pascal_name, NULL, NULL, NULL);
  2815.         NoteAlert(message_note_alert, (ModalFilterProcPtr)0);
  2816.         }
  2817.  
  2818. message_alert(format_str, arg0, arg1, arg2, arg3, arg4, arg5)
  2819. char    *format_str;
  2820. long    arg0, arg1, arg2, arg3, arg4, arg5;
  2821. {
  2822. Str255  pascal_name;
  2823.         InitCursor();
  2824.         sprintf(message_string, format_str,
  2825.                         arg0, arg1, arg2, arg3, arg4, arg5);
  2826.         pascal_name[0] = strlen(message_string);
  2827.         strcpy((char *) &pascal_name[1], message_string);
  2828.         ParamText(&pascal_name, NULL, NULL, NULL);
  2829.         StopAlert(message_alert_alert, (ModalFilterProcPtr)0);
  2830.         }
  2831.  
  2832. /*
  2833. ** Copyright (c) 1988 By Tim Endres
  2834. ** 8840 Main St.
  2835. ** Whitmore Lake, Mi.  48189
  2836. **
  2837. ** Written by Tim Endres.
  2838. */
  2839.  
  2840. #define getInit         -1              /* Initialize */
  2841. #define getMenu         102             /* Folder Menu Mouse */
  2842. #define getFolder       103             /* Open Folder */
  2843. #define getUseDir       11              /* Use This Directory Button */
  2844.  
  2845.  
  2846. #define GETDIRECT_DIALOG        6767
  2847. #define GETDIRHLP_DIALOG        6765
  2848. #define prompt_item                     11
  2849. #define select_item                     12
  2850. #define help_item                       13
  2851.  
  2852. #define getInit                         -1              /* Initialize */
  2853. #define getStaySF                       0
  2854. #define getIdle                         100             /* Idle routine  */
  2855. #define redrawFiles                     101             /* Redraw the files in t
  2856. he list */
  2857. #define getMenu                         102             /* Folder Menu Mouse */
  2858. #define getFolder                       103             /* Open Folder */
  2859.  
  2860. static SFReply                          getDir_Reply;
  2861. static char                                     getDir_prompt[256];
  2862. static char                                     save_fName0;
  2863. static OSType                           save_fType;
  2864.  
  2865. void
  2866. show_getdir_help(parent)
  2867. DialogPtr       parent;
  2868.         {
  2869.         short           itemhit, done;
  2870.         DialogPtr       mydialog;
  2871.         GrafPtr         saveport;
  2872.         Handle          dlogrsrc;
  2873.         Rect            *rect_ptr;
  2874.         Point           mypt;
  2875.  
  2876.         GetPort(&saveport);
  2877.  
  2878.         InitCursor();
  2879.         dlogrsrc = GetResource((ResType)'DLOG', (short)GETDIRHLP_DIALOG);
  2880.         if (dlogrsrc != NULL) {
  2881.                 LoadResource(dlogrsrc);
  2882.                 rect_ptr = (Rect *) *dlogrsrc;
  2883.                 mypt.v = parent->portRect.bottom - (8 + (rect_ptr->bottom - rect_ptr->top));
  2884.                 mypt.h = parent->portRect.left + 8;
  2885.                 LocalToGlobal(&mypt);
  2886.                 OffsetRect(rect_ptr, (mypt.h - rect_ptr->left), (mypt.v - rect_ptr->top));
  2887.                 }
  2888.         mydialog = GetNewDialog(GETDIRHLP_DIALOG, NULL, (void *) -1 /* inFront */);
  2889.         if (mydialog == NULL)
  2890.                 {
  2891.                 SysBeep(0);
  2892.                 return;
  2893.                 }
  2894.  
  2895.         SetPort(mydialog);
  2896.         TextFont(geneva);
  2897.         TextSize(9);
  2898.  
  2899.         for (done=0; ! done; )  {
  2900.                 SetPort(mydialog);
  2901.                 ModalDialog((ModalFilterProcPtr)0, &itemhit);
  2902.                 switch (itemhit) {
  2903.                         case ok:
  2904.                                 done = 1;
  2905.                                 break;
  2906.                         }
  2907.                 }
  2908.  
  2909.         DisposDialog(mydialog);
  2910.         SetPort(saveport);
  2911.         return;
  2912.         }
  2913.  
  2914. pascal short GetDirHook(item, dialog)
  2915. short           item;
  2916. DialogPtr       dialog;
  2917. {
  2918. int             need_check = 0;
  2919.  
  2920.         switch (item) {
  2921.                 case getInit:
  2922.                         need_check = 0;
  2923.                         save_fName0 = getDir_Reply.fName[0];
  2924.                         save_fType  = getDir_Reply.fType;
  2925.                         MySetText(dialog, prompt_item, getDir_prompt);
  2926.                         MyHiliteControl(dialog, select_item, 255);
  2927.                         break;
  2928.                 case getOpen:                           /* Open or DoubleClick w
  2929. ith selected file... */
  2930.                         item = getStaySF;
  2931.                         need_check = 1;
  2932.                         break;
  2933.                 case getFolder:                         /* Open or DoubleClick w
  2934. ith selected folder... */
  2935.                         need_check = 1;
  2936.                         break;
  2937.                 case select_item:
  2938.                         item = getOpen;
  2939.                         break;
  2940.                 case help_item:
  2941.                         show_getdir_help(dialog);
  2942.                         item = getStaySF;
  2943.                         break;
  2944.                 case getCancel:
  2945.                         break;
  2946.                 case getMenu:
  2947.                 case getNmList:
  2948.                 case getScroll:
  2949.                         need_check = 1;
  2950.                         break;
  2951.                 case getIdle:
  2952.                         break;
  2953.                 default:        /* Key down's are 1000 + ASCII-code */
  2954.                         need_check = 1;
  2955.                         break;
  2956.                 }
  2957.  
  2958.         if (! need_check)
  2959.                 {
  2960.                 if (save_fName0 != getDir_Reply.fName[0]
  2961.                         || save_fType != getDir_Reply.fType)
  2962.                         need_check = 1;
  2963.                 }
  2964.         if (need_check)
  2965.                 {
  2966.                 if (getDir_Reply.fName[0] == '\0' && getDir_Reply.fType == 0)
  2967.                         {
  2968.                                 /* NOTHING Selected... */
  2969.                         MyHiliteControl(dialog, select_item, 0);
  2970.                         }
  2971.                 else if (getDir_Reply.fName[0] == '\0')
  2972.                         {
  2973.                                 /* DIRECTORY */
  2974.                         MyHiliteControl(dialog, select_item, 0);
  2975.                         }
  2976.                 else
  2977.                         {
  2978.                                 /* FILE */
  2979.                         MyHiliteControl(dialog, select_item, 255);
  2980.                         /* item = getStaySF; */
  2981.                         }
  2982.  
  2983.                 save_fName0 = getDir_Reply.fName[0];
  2984.                 save_fType  = getDir_Reply.fType;
  2985.                 need_check = 0;
  2986.                 }
  2987.  
  2988.         return item;
  2989.         }
  2990.  
  2991. pascal Boolean NoFiles(pb)
  2992. FileParam *pb;
  2993. {
  2994. #pragma unused (pb)
  2995.  
  2996.         return false;
  2997.         }
  2998.  
  2999. GetFolderPathName(prompt, path_name, volref, dirid)
  3000. char    *prompt;
  3001. char    *path_name;
  3002. short   *volref;
  3003. long    *dirid;
  3004. {
  3005. SFTypeList              mytypes;
  3006. Point                   mypoint;
  3007. int                             len;
  3008. WindowPtr               myWindow;
  3009.  
  3010.         strcpy(getDir_prompt, prompt);
  3011.  
  3012.         myWindow = FrontWindow();
  3013.  
  3014.         /* gdhfp = (FILE *)0; */
  3015.  
  3016.         mypoint.h = mypoint.v = 75;
  3017.         SFPGetFile(mypoint, "\p", NoFiles, -1, mytypes, GetDirHook,
  3018.                                         &getDir_Reply, GETDIRECT_DIALOG, (ModalFilterProcPtr)0);
  3019.         if (getDir_Reply.good) {
  3020.  
  3021.                 if (getDir_Reply.fName[0] != '\0') {
  3022.                         *volref = WDVolRef(getDir_Reply.vRefNum);
  3023.                         *dirid = WDDirID(getDir_Reply.vRefNum);
  3024.                         pathname(path_name, getDir_Reply.vRefNum);
  3025.                         }
  3026.                 else {
  3027.                         dirpathname(path_name, getDir_Reply.vRefNum, getDir_Reply.fType);
  3028.                         *volref = getDir_Reply.vRefNum;
  3029.                         *dirid = getDir_Reply.fType;
  3030.                         }
  3031.  
  3032.                 len = strlen(path_name);
  3033.                 if (path_name[len - 1] == ':')
  3034.                         path_name[len - 1] = '\0';      /* Drop Colon */
  3035.  
  3036.                 return 1;
  3037.                 }
  3038.         else
  3039.                 return 0;
  3040.         }
  3041.  
  3042.  
  3043. #define getInit                 -1              /* Initialize */
  3044. #define d_sfgetfile_id  777
  3045. #define getPromptItem   11
  3046.  
  3047. static  char    get_prompt[256];
  3048.  
  3049. pascal short PromptHook(item, dialog)
  3050. short           item;
  3051. DialogPtr       dialog;
  3052. {
  3053.         switch (item) {
  3054.                 case getInit:
  3055.                         MySetText(dialog, getPromptItem, get_prompt);
  3056.                         get_prompt[0] = '\0';
  3057.                         break;
  3058.                 }
  3059.         return item;
  3060.         }
  3061.  
  3062.  
  3063. MyPutFile(where, prompt, orig, hook, reply)
  3064. Point   where;
  3065. char    *prompt;
  3066. char    *orig;
  3067. DlgHookProcPtr  hook;
  3068. SFReply *reply;
  3069. {
  3070.         SFPutFile(where, prompt, orig, hook, reply);
  3071.         }
  3072.  
  3073. MyGetFile(sfpoint, sfprompt, sffilter, sfnumtypes, sftypes, sfhook, sfreply)
  3074. Point           sfpoint;
  3075. char            *sfprompt;
  3076. FileFilterProcPtr       sffilter;
  3077. int                     sfnumtypes;
  3078. SFTypeList      sftypes;
  3079. char            *sfhook;
  3080. SFReply         *sfreply;
  3081. {
  3082. #pragma unused (sfhook)
  3083.  
  3084.         strncpy(get_prompt, &sfprompt[1], sfprompt[0]);
  3085.         get_prompt[sfprompt[0]] = '\0';
  3086.  
  3087.         SFPGetFile(sfpoint, "\p", sffilter, sfnumtypes,
  3088.                                 sftypes, PromptHook, sfreply, d_sfgetfile_id,
  3089.                                 (ModalFilterProcPtr)0);
  3090.         }
  3091.  
  3092. /* My hacks */
  3093.  
  3094. #ifdef Undefined
  3095. int
  3096. pathname(char *path, int wd)
  3097. {
  3098.     GetPathNameFromWD(path,NULL,wd);
  3099.     p2cstr(path);
  3100. }
  3101.  
  3102. int
  3103. fullname(char *path, int wd, char *name)
  3104. {
  3105.     GetPathNameFromWD(path,name,wd);
  3106.     p2cstr(path);
  3107. }
  3108. #endif
  3109.  
  3110. filter_unix_string(into, from)
  3111. char    *into;
  3112. char    *from;
  3113. {
  3114. char    *ptr;
  3115.  
  3116.     ptr = into;
  3117.     for ( ; *from ; ) {
  3118.         if (*from == '\\') {
  3119.             switch (*(from + 1)) {
  3120.                 case '\\':
  3121.                     *ptr++ = '\\'; from += 2;
  3122.                     break;
  3123.                 case 'r':
  3124.                     *ptr++ = '\015'; from += 2;
  3125.                     break;
  3126.                 case 'n':
  3127.                     *ptr++ = '\012'; from += 2;
  3128.                     break;
  3129.                 case 't':
  3130.                     *ptr++ = '\011'; from += 2;
  3131.                     break;
  3132.                 default:
  3133.                     if (isdigit(*(from+1)) &&
  3134.                         isdigit(*(from+2)) &&
  3135.                         isdigit(*(from+3)))
  3136.                         {
  3137.                         *ptr = ((*(from+1) - '0') * 64) +
  3138.                                 ((*(from+2) - '0') * 8) +
  3139.                                 (*(from+3) - '0');
  3140.                         ptr++; from += 4;
  3141.                         }
  3142.                     else {
  3143.                         *ptr++ = *from++;
  3144.                         }
  3145.                     break;
  3146.                 }
  3147.             }
  3148.         else
  3149.             *ptr++ = *from++;
  3150.         }
  3151.     
  3152.     *ptr = '\0';
  3153.     
  3154.     return (int)(ptr - into);
  3155.     }
  3156.  
  3157. CheckOption()
  3158. {
  3159. KeyMap    mykeys;
  3160.  
  3161.     GetKeys(mykeys);
  3162.     return (mykeys[1] & 0x00000004) != 0;
  3163.     }
  3164.  
  3165. #define TSigWord        0x4244
  3166.  
  3167. char    *prepstr();
  3168.  
  3169. char    *
  3170. fullname(name, vrefnum, filename)
  3171. char            *name;
  3172. int                     vrefnum;
  3173. char            *filename;
  3174. {
  3175. char                    volname[32];
  3176. HVolumeParam    pb;
  3177.  
  3178.         strcpy(name, filename);
  3179.  
  3180.         pb.ioVRefNum = vrefnum;
  3181.         pb.ioNamePtr = (unsigned char *) volname; volname[0] = '\0';
  3182.         pb.ioVolIndex = 0;
  3183.         PBHGetVInfo((HParmBlkPtr)&pb, FALSE);   /* Works with 64K ROMs as well.
  3184. */
  3185.         p2cstr(volname);
  3186.         if (pb.ioVSigWord == 0x4244)
  3187.                 _prep_hfs_name(name, vrefnum);
  3188.         else
  3189.                 prepstr(name, volname);
  3190.         return name;
  3191.         }
  3192.  
  3193. char    *
  3194. pathname(pathname, vrefnum)
  3195. char            *pathname;
  3196. int                     vrefnum;
  3197. {
  3198. char                    volname[32];
  3199. HVolumeParam    pb;
  3200.  
  3201.         pathname[0] = '\0';
  3202.  
  3203.         pb.ioVRefNum = vrefnum;
  3204.         pb.ioNamePtr = (unsigned char *) volname; volname[0] = '\0';
  3205.         pb.ioVolIndex = 0;
  3206.         PBHGetVInfo((HParmBlkPtr)&pb, FALSE);   /* Works with 64K ROMs as well.
  3207. */
  3208.         p2cstr(volname);
  3209.         if (pb.ioVSigWord == 0x4244)
  3210.                 _prep_hfs_name(pathname, vrefnum);
  3211.         else
  3212.                 prepstr(pathname, volname);
  3213.         return pathname;
  3214.         }
  3215.  
  3216. _prep_hfs_name(fullname, vrefnum)
  3217. char    *fullname;
  3218. int             vrefnum;
  3219. {
  3220. CInfoPBRec      cpb;
  3221. WDPBRec         wpb;
  3222. char            myname[256];
  3223.  
  3224.         wpb.ioNamePtr = (unsigned char *) myname; myname[0] = '\0';
  3225.         wpb.ioVRefNum = vrefnum;
  3226.         wpb.ioWDIndex = 0;
  3227.         wpb.ioWDProcID = (long) 0;
  3228.         PBGetWDInfo(&wpb, FALSE);
  3229.  
  3230.         cpb.dirInfo.ioVRefNum = vrefnum;
  3231.         cpb.dirInfo.ioNamePtr = (unsigned char *) myname; myname[0] = '\0';
  3232.         cpb.dirInfo.ioDrDirID = wpb.ioWDDirID;
  3233.         cpb.dirInfo.ioFDirIndex = -1;
  3234.         PBGetCatInfo(&cpb, FALSE);
  3235.         p2cstr(myname);
  3236.         prepstr(fullname, myname);
  3237.  
  3238.         while (cpb.dirInfo.ioDrDirID != 2) {
  3239.                 cpb.dirInfo.ioDrDirID = cpb.dirInfo.ioDrParID;
  3240.                 cpb.dirInfo.ioNamePtr = (unsigned char *) myname; myname[0] = '\0';
  3241.                 cpb.dirInfo.ioFDirIndex = -1;
  3242.                 PBGetCatInfo(&cpb, FALSE);
  3243.                 p2cstr(myname);
  3244.                 prepstr(fullname, myname);
  3245.                 }
  3246.         }
  3247.  
  3248. char    *
  3249. dirpathname(pathname, vrefnum, dirid)
  3250. char            *pathname;
  3251. int                     vrefnum;
  3252. long            dirid;
  3253. {
  3254. char                    volname[32];
  3255. HVolumeParam    pb;
  3256.  
  3257.         pathname[0] = '\0';
  3258.  
  3259.         pb.ioVRefNum = vrefnum;
  3260.         pb.ioNamePtr = (unsigned char *) volname; volname[0] = '\0';
  3261.         pb.ioVolIndex = 0;
  3262.         PBHGetVInfo((HParmBlkPtr)&pb, FALSE);
  3263.         p2cstr(volname);
  3264.         if (pb.ioVSigWord == 0x4244)
  3265.                 _dir_prep_hfs_name(pathname, vrefnum, dirid);
  3266.         else
  3267.                 prepstr(pathname, volname);
  3268.         return pathname;
  3269.         }
  3270.  
  3271. _dir_prep_hfs_name(fullname, vrefnum, dirid)
  3272. char    *fullname;
  3273. int             vrefnum;
  3274. long    dirid;
  3275. {
  3276. CInfoPBRec      cpb;
  3277. char            myname[256];
  3278.  
  3279.         cpb.dirInfo.ioVRefNum = vrefnum;
  3280.         cpb.dirInfo.ioNamePtr = (unsigned char *) myname; myname[0] = '\0';
  3281.         cpb.dirInfo.ioDrDirID = dirid;
  3282.         cpb.dirInfo.ioFDirIndex = -1;
  3283.         PBGetCatInfo(&cpb, FALSE);
  3284.         p2cstr(myname);
  3285.         prepstr(fullname, myname);
  3286.  
  3287.         while (cpb.dirInfo.ioDrDirID != 2) {
  3288.                 cpb.dirInfo.ioDrDirID = cpb.dirInfo.ioDrParID;
  3289.                 cpb.dirInfo.ioNamePtr = (unsigned char *) myname; myname[0] = '\0';
  3290.                 cpb.dirInfo.ioFDirIndex = -1;
  3291.                 PBGetCatInfo(&cpb, FALSE);
  3292.                 p2cstr(myname);
  3293.                 prepstr(fullname, myname);
  3294.                 }
  3295.         }
  3296.  
  3297. char    *
  3298. prepstr(s1, s2)
  3299. char            *s1, *s2;
  3300. {
  3301. register char   *ptr1, *ptr2;
  3302. char                    tempstr[256];
  3303.  
  3304.         ptr1 = tempstr;
  3305.         ptr2 = s2;
  3306.         while (*ptr1++ = *ptr2++) ;
  3307.         ptr1--; *ptr1++ = ':';
  3308.         ptr2 = s1;
  3309.         while (*ptr1++ = *ptr2++) ;
  3310.         ptr1 = tempstr; ptr2 = s1;
  3311.         while (*ptr2++ = *ptr1++) ;
  3312.         return s1;
  3313.         }
  3314.  
  3315. /* I provided the following routine since it was missing from Tim Endres' code,
  3316. and it seemed an easy one.  If it's wrong, it's my fault - Eric. */
  3317.  
  3318. int MissedAnyParameters(AppleEvent *theEvent)
  3319. {
  3320.    DescType returnedType;
  3321.    Size     actualSize;
  3322.    OSErr    err;
  3323.  
  3324.    err = AEGetAttributePtr ( theEvent, keyMissedKeywordAttr, 
  3325.                         typeWildCard, &returnedType, NULL, 0, 
  3326.                         &actualSize);
  3327.    
  3328.    return err != errAEDescNotFound;
  3329. }
  3330.  
  3331. /* The following routine handles the misc dosc event which your application
  3332. should support.  How you integrate it into your app depends largely on the
  3333. structure of said app.  I have installed it by adding a DoAppleEvent method
  3334. to my application subclass which checks each AppleEvent to see if it is
  3335. 'misc' 'dosc'.  If so, this routine is called. CUSTOM */
  3336.  
  3337. pascal OSErr
  3338. AEDoScriptHandler(AppleEvent *message,AppleEvent *reply,long refnum)
  3339. {
  3340. int                     result = noErr, myerr, tcl_result = TCL_OK;
  3341. char            error_str[128];
  3342. AEDesc          theDesc;
  3343. FSSpec          theFSS;
  3344. long            length;
  3345. Handle          result_handle, stdout_handle;
  3346. DescType        ignoredType;
  3347. Size            ignoredSize;
  3348. extern int      tcl_feedback_output();
  3349. #pragma unused (reply, refnum)
  3350.  
  3351.         result_handle = NewHandle(0);
  3352.         stdout_handle = NewHandle(0);
  3353.         if (result_handle != NULL && stdout_handle != NULL) {
  3354.                 myerr = AEGetParamDesc(message, keyDirectObject, typeWildCard, & theDesc);
  3355.                 if (myerr != noErr) {
  3356.                         sprintf(error_str, "GetParamDesc error %d in Do Script", myerr);
  3357.                         Feedback("%s", error_str);
  3358.                         myerr = AEPutParamPtr(reply, keyErrorString, typeChar,
  3359.                                                                         error_str, strlen(error_str));
  3360.                         result = myerr;
  3361.                         }
  3362.                 else if (! MissedAnyParameters(message)) {
  3363.                         /* Got all the parameters we need. Now, go through the direct object, */
  3364.                         /* see what type it is, and parse it up. */
  3365.                         if (theDesc.descriptorType == (DescType)'TEXT')
  3366.                                 {
  3367.                                 length = GetHandleSize(theDesc.dataHandle);
  3368.                                 SetHandleSize(theDesc.dataHandle, length + 1);
  3369.                                 if (MemError() == noErr) {
  3370.                                         * (*theDesc.dataHandle + length) = '\0';
  3371.  
  3372.                                         tcl_result = run_DoScript(theDesc.dataHandle, result_handle, stdout_handle);
  3373.  
  3374.                                         length = GetHandleSize(result_handle);
  3375.                                         HLock(result_handle);
  3376.                                         myerr = AEPutParamPtr( reply, keyDirectObject,
  3377.  
  3378.         typeChar, *result_handle, length );
  3379.                                         HUnlock(result_handle);
  3380.  
  3381.                                         length = GetHandleSize(stdout_handle);
  3382.                                         HLock(stdout_handle);
  3383.                                         myerr = AEPutParamPtr(  reply,
  3384.  
  3385.         (tcl_result==TCL_OK ? keyStdOutObject : keyErrorString),
  3386.  
  3387.         typeChar, *stdout_handle, length );
  3388.                                         HUnlock(stdout_handle);
  3389.  
  3390.                                         result = (tcl_result == TCL_OK ? noErr : -1769);
  3391.                                         }
  3392.                                 else
  3393.                                         {
  3394.                                         result = MemError();
  3395.                                         sprintf(error_str, "Error %d adding terminating zero in AEDoScript.", result);
  3396.                                         Feedback("%s", error_str);
  3397.                                         myerr = AEPutParamPtr(reply, keyErrorString, typeChar,
  3398.  
  3399.         error_str, strlen(error_str));
  3400.                                         }
  3401.                                 }
  3402.                         else if (theDesc.descriptorType == (DescType)'alis')
  3403.                                 {
  3404.                                 myerr = AEGetParamPtr(  message,
  3405.                                 keyDirectObject, typeFSS, &ignoredType,
  3406.                                 (Ptr)&theFSS, sizeof(theFSS), &ignoredSize
  3407.                                 );
  3408.                                 if (myerr == noErr)
  3409.                                         {
  3410.                                         Feedback("AEDoScriptHandler: Execute script file '%.*s'.",
  3411.                                                                         theFSS.name[0], &theFSS.name[1]);
  3412.  
  3413.                                         tcl_result = run_AE_tcl_script(&theFSS,result_handle, stdout_handle);
  3414.  
  3415.                                         Feedback("AEDoScriptHandler: tcl_result= %d. Result len = %d StdOut len = %d.",
  3416.                                                         tcl_result, GetHandleSize(result_handle), GetHandleSize(stdout_handle));
  3417.  
  3418.                                         length = GetHandleSize(result_handle);
  3419.                                         HLock(result_handle);
  3420.                                         myerr = AEPutParamPtr( reply, keyDirectObject,
  3421.  
  3422.         typeChar, *result_handle, length );
  3423.                                         HUnlock(result_handle);
  3424.  
  3425.                                         length = GetHandleSize(stdout_handle);
  3426.                                         HLock(stdout_handle);
  3427.                                         myerr = AEPutParamPtr(  reply,
  3428.  
  3429.         (tcl_result==TCL_OK ? keyStdOutObject : keyErrorString),
  3430.  
  3431.         typeChar, *stdout_handle, length );
  3432.                                         HUnlock(stdout_handle);
  3433.  
  3434.                                         result = (tcl_result == TCL_OK ? noErr : -1769);
  3435.                                         }
  3436.                                 else
  3437.                                         {
  3438.                                         sprintf(error_str, "AEDoScriptHandler: Error #%d AEGetParamPtr(typeFSS).", myerr);
  3439.                                         Feedback("%s", error_str);
  3440.                                         myerr = AEPutParamPtr(reply, keyErrorString, typeChar,
  3441.  
  3442.         error_str, strlen(error_str));
  3443.                                         result = myerr;
  3444.                                         }
  3445.                                 }
  3446.                         else
  3447.                                 {
  3448.                                 sprintf(error_str, "invalid script type '%-4.4s', must be 'alis' or 'TEXT'",
  3449.                                                         &theDesc.descriptorType);
  3450.                                 Feedback("%s", error_str);
  3451.                                 myerr = AEPutParamPtr(reply, keyErrorString, typeChar,
  3452. error_str, strlen(error_str));
  3453.                                 result = -1770;
  3454.                                 }
  3455.  
  3456.                         }
  3457.                 else
  3458.                         {
  3459.                         sprintf(error_str, "AEDoScriptHandler: MissedAnyParameters!!!");
  3460.                         Feedback("%s", error_str);
  3461.                         myerr = AEPutParamPtr(reply, keyErrorString, typeChar,
  3462.                                                                         error_str, strlen(error_str));
  3463.                         result = -1771;
  3464.                         }
  3465.  
  3466.                 if (myerr = AEDisposeDesc(&theDesc))
  3467.                         Feedback("Error %d AEDisposeDesc in Do Script.", myerr);
  3468.  
  3469.                 }
  3470.         else
  3471.                 {
  3472.                 sprintf(error_str, "Error %d allocating result handle in AEDoScript.", result);
  3473.                 Feedback("%s", error_str);
  3474.                 myerr = AEPutParamPtr(reply, keyErrorString, typeChar,
  3475.                                                                 error_str, strlen(error_str));
  3476.                 result = MemError();
  3477.                 }
  3478.  
  3479.         if (result_handle != NULL)
  3480.                 DisposHandle(result_handle);
  3481.         if (stdout_handle != NULL)
  3482.                 DisposHandle(stdout_handle);
  3483.  
  3484.         return result;
  3485.         }
  3486.  
  3487. int WDDirID(short vRefNum)
  3488. {
  3489.  
  3490.     WDPBRec    myBlock;
  3491.  
  3492.     /*
  3493.     /* PBGetWDInfo has a bug under A/UX 1.1.  If vRefNum is a real vRefNum
  3494.     /* and not a wdRefNum, then it returns garbage.  Since A/UX has only 1
  3495.     /* volume (in the Macintosh sense) and only 1 root directory, this can
  3496.     /* occur only when a file has been selected in the root directory (/).
  3497.     /* So we look for this and hardcode the DirID and vRefNum. */
  3498.  
  3499.     myBlock.ioNamePtr = NULL;
  3500.     myBlock.ioVRefNum = vRefNum;
  3501.     myBlock.ioWDIndex = 0;
  3502.     myBlock.ioWDProcID = 0;
  3503.  
  3504.     /* Change the Working Directory number in vRefnum into a real vRefnum */
  3505.     /* and DirID. The real vRefnum is returned in ioVRefnum, and the real */
  3506.     /* DirID is returned in ioWDDirID. */
  3507.  
  3508.     PBGetWDInfo(&myBlock,false);
  3509.  
  3510.     return myBlock.ioWDDirID;
  3511. }
  3512.  
  3513. int WDVolRef(short vRefNum)
  3514. {
  3515.  
  3516.     WDPBRec    myBlock;
  3517.  
  3518.     /*
  3519.     /* PBGetWDInfo has a bug under A/UX 1.1.  If vRefNum is a real vRefNum
  3520.     /* and not a wdRefNum, then it returns garbage.  Since A/UX has only 1
  3521.     /* volume (in the Macintosh sense) and only 1 root directory, this can
  3522.     /* occur only when a file has been selected in the root directory (/).
  3523.     /* So we look for this and hardcode the DirID and vRefNum. */
  3524.  
  3525.     myBlock.ioNamePtr = NULL;
  3526.     myBlock.ioVRefNum = vRefNum;
  3527.     myBlock.ioWDIndex = 0;
  3528.     myBlock.ioWDProcID = 0;
  3529.  
  3530.     /* Change the Working Directory number in vRefnum into a real vRefnum */
  3531.     /* and DirID. The real vRefnum is returned in ioVRefnum, and the real */
  3532.     /* DirID is returned in ioWDDirID. */
  3533.  
  3534.     PBGetWDInfo(&myBlock,false);
  3535.  
  3536.     return myBlock.ioWDVRefNum;
  3537. }
  3538.  
  3539. void RotateCursor(int x) {
  3540.     gApplication->SpinCursor();    /* CUSTOM */
  3541. }
  3542.  
  3543.